☰
Git从安装到实战:版本控制原理、分支合并与SSH配置全攻略
2026/9/29 9:58:44 网站建设 项目流程

如果你搜到这里,大概率不是想听“Git是一个分布式版本控制系统”这种教科书定义,而是遇到了具体问题:git安装不上、装上了系统不识别、提交代码报错、分支合并搞出冲突,或者单纯想把日常工作里反复敲的那几条命令真正搞明白。我最初用Git的时候也踩过不少坑,最离谱的一次是把整个项目文件夹复制了一份当“手动版本回退”,后来才老老实实把Git的基础链路吃透。

这篇文章没有太多高深理论,就是从零开始,把Git的安装、配置、日常命令、分支操作、远程仓库对接,以及高频报错的排查思路完整串一遍。不管你是Windows、macOS还是Ubuntu用户,刚接触Git的初学者,还是已经被工作蹂躏了一阵子的“熟练工”,只要按着这篇文章走一遍,大概率能把Git从“只会敲命令”提升到“知道为什么这么敲”。文里涉及的所有操作我都实测过,版本号、报错信息、解决方案都是真实碰到的,可以直接照抄。

1. 从“版本”到“仓库”:Git到底在做一件什么事

先别急着装软件,把Git的底层逻辑搞清楚,后面所有命令你都不需要死记硬背。

1.1 版本管理解决的核心问题

假设你正在写一份文档,改到第三版后觉得第二版更好,又没有备份,怎么办?以前的做法是手动存好几个副本:“论文_最终版.doc”“论文_终稿_不改版.doc”“论文_打死也不改版.doc”。项目代码比文档复杂得多,多人协作时,你改你的、我改我的,最后还得手动合并文件,这在现代软件开发里根本不可行。

版本控制工具就是来解决这个问题的:给文件系统装一台“时间机器”。每一次提交(commit)都像给当前项目拍一张快照,任何时候都能回到任意一次快照的状态。Git只是众多版本控制工具中的一种,但它的设计思路和早期的SVN、CVS有根本区别,理解了这些区别,你就理解了Git设计命令时的出发点。

1.2 快照存储与差异存储的本质区别

SVN这类集中式版本控制工具,存的是“文件变化前后的差异”,每次历史版本都记录“这个文件在这个版本里改了哪几行”。好处是省存储空间,坏处是历史越长,回溯一次版本就越慢,而且一旦中央服务器挂了,本地基本就废了。

Git不一样,它采用“快照流”的方式。每次提交时,Git把当前所有文件的状态整体拍一张照,如果有文件没变,就直接引用上一个版本的相同文件,只有变化的文件才新增存储。你可以把Git仓库想象成一个不断增长的相册,每张相册对应一次提交,每张照片都完整记录当前所有文件的状态。相同内容的照片不重复洗印,只挂一个索引指向旧照片。这样做的结果是:回溯历史极快,因为每张快照都是完整的;存储效率也没有想象中那么低,因为相同文件被复用了。

1.3 分布式架构到底“分布”了什么

SVN是集中式的,代码只存在中央服务器上,所有人提交都打到同一台机器。Git是分布式的,每个开发者的本地目录都包含一份完整的仓库,包括全部历史记录。这意味着:

  • 没网也能提交代码,提交操作完全在本地完成;
  • 本地就是完整的备份,服务器挂了也能从任何一台开发机恢复;
  • 各人可以在本地大规模修改、试验,再决定要不要推到远端。

我第一次体会到这个优势是出差坐高铁,笔记本没网,但手里的代码照常提交了十几个版本,到酒店再一次性推到远程仓库,过程毫无压力。换成SVN,离线状态下连提交都做不到。

1.4 分支为什么“便宜”

用过SVN的人应该都有印象,创建分支通常是“复制一组完整代码到另一个目录”,又慢又占用空间,所以大家轻易不敢开分支。Git的分支本质上只是一个指向某次提交的指针,创建分支就是在仓库里新建一个41字节的指针文件,成本几乎为零,这也是Git工作流鼓励“多开分支、频繁开分支”的根本原因。

仓库根目录下的.git文件夹,就是这个项目的所有“时间机器照片”和指针信息。你平时看到的文件目录叫“工作区”,.git文件夹里存的是“版本库”。后续几乎所有Git操作,本质都是在工作区和这个.git版本库之间搬运数据。

2. Windows下的安装与配置:镜像下载、PATH选项、Git Bash与全局设置

Git装起来不复杂,但安装选项里有个坑,直接影响后面能不能被IDEA、VSCode这类工具识别。搜“git安装教程”的人很多,其实卡点就那么两三个,我逐个说清楚。

2.1 下载渠道:官网慢,就用国内镜像

Git官网的Windows安装包下载速度不稳定,尤其几十上百MB的安装包,挂半天下不动是常事。国内镜像速度快得多,我用得比较多的是两个:

  • 淘宝npm镜像:https://npm.taobao.org/mirrors/git-for-windows/
  • 华为云镜像:https://mirrors.huaweicloud.com/git-for-windows/

打开后选择对应版本,Windows用户下载类似Git-2.xx.x-64-bit.exe的文件。注意区分64位和32位,现在新电脑基本都是64位。macOS用户可以用brew install git,Ubuntu用户直接sudo apt install git,网络干净利落,反而没有Windows这么折腾。

2.2 安装过程中最关键的三个选项

安装包一路Next会出现几个决定命运的选项,别只顾点“下一步”:

第一个是Select Components(选择组件),默认选项基本够用,但建议额外勾选“Git Bash Here”和“Git GUI Here”,右键菜单里直接打开Git Bash,后面操作方便很多。

第二个是Choosing the default editor(默认编辑器),默认是Vim。如果你没学过Vim,在Git里提交代码时不小心进入了Vim界面会懵住。建议选“Use the Nano editor”或者直接选择你常用的编辑器,我用的是VS Code,提交信息时直接用VS Code编辑,体验好得多。

第三个是决定成败的PATH环境变量选项,它有三个选择:

  • 第一个“Use Git from Git Bash only”:只在Git Bash里能用git命令;
  • 第二个“Git from the command line and also from 3rd-party software”:把Git加入系统PATH,CMD、PowerShell、IDEA、VSCode都能直接调用;
  • 第三个“Use Git and optional Unix tools from Command Prompt”:会在PATH里加入一堆Unix命令,某些情况下会跟Windows自带命令冲突,不建议。

很多人装完Git,在CMD窗口敲git提示“不是内部或外部命令”,就是选了第一个选项或者安装组件时有遗漏。选第二个,问题直接消失。IDEA、VSCode这些工具搜索不到Git路径,也是因为没选这个选项。

2.3 验证安装与Git Bash的妙用

安装完成后,打开CMD或PowerShell,输入:

git --version

正常会输出类似git version 2.40.0.windows.1的版本信息。如果提示git : 无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称,基本就是PATH配置问题。解决方法:重新运行安装包,选择“Modify”,把刚才的PATH选项改成第二个;或者手动把C:\Program Files\Git\cmd加进系统环境变量。改完重启终端再试。

Git Bash是跟随Git一起安装的轻量级Unix模拟环境,它的价值超出很多人的认知。Windows的CMD对Linux风格的路径、命令支持很差,脚本写起来也麻烦,Git Bash能让你在Windows上使用Linux风格的命令,比如ls、grep、sed、ssh。我日常所有Git操作和轻量脚本都优先用Git Bash而不是CMD或PowerShell,少踩很多路径分隔符的坑。

2.4 全局配置:提交者的名片

Git每次提交都必须知道“是谁提交的”,这靠用户名和邮箱标识。安装完成后第一件事就是配置全局用户信息:

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

可以用git config --list查看所有配置,确认是否设置成功。--global表示对当前系统当前用户生效,所有仓库共用这套身份。如果单个项目需要不同身份(比如工作仓库用公司邮箱、个人仓库用私人邮箱),可以进入仓库目录后去掉--global重新配置,只对当前仓库生效。

还有一个容易被忽略的配置,中文文件名乱码问题。Windows下终端用GBK编码,而Git内部用UTF-8,解决方法:

git config --global core.quotepath false

配完后中文文件名不再显示成八进制转义序列“\346\265\213”,直接显示正常中文。

3. 从空目录到第一次提交:add/commit/log/diff 的完整链路

安装好、配置好之后,进入Git日常使用的主战场。这条链路是从零到一的核心,几乎每天都要走一遍。

3.1 初始化仓库与第一次提交

进入项目目录,执行:

git init

当前目录就变成了一个Git仓库,master或main分支会随之诞生。之后用git status查看当前仓库状态,会看到一堆未跟踪文件,说明这些文件还没进入Git的版本管理体系。

把文件加入版本管理需要两步:

git add . # 把所有改动加入暂存区 git commit -m "初始化提交" # 把暂存区内容生成一个版本快照

新手最容易困惑的是:add和commit为什么要分开?直接提交不好吗?这里涉及Git特有的“暂存区”设计。add是把文件放进一个叫“暂存区”的中间地带,commit才真正把暂存区的内容拍成快照存入版本库。为什么要设置中间地带?因为真实工作中经常会出现“这个版本只提这3个文件,另外两个文件还在改,不想一起打包”的场景。暂存区允许你精细控制一次提交到底包含哪些改动。类比一下:add是把菜装进购物车,commit是结账买单,你可以在结账前随时把某些菜放回货架。

3.2 status 和 diff:先搞清楚发生了什么,再动手

git status是我个人使用频率最高的命令,没有之一。每次操作前看一眼状态,能避免90%的误操作。它告诉你三个信息:哪些文件改动了、哪些已经暂存、哪些还未跟踪。

git diff负责查看具体改动内容:

git diff # 工作区与暂存区的差异 git diff --cached # 暂存区与上一次提交的差异

我习惯在add之前用git diff检查自己改了哪些内容,确认无误后再add;add之后再用git diff --cached复查一遍即将提交的内容。这个习惯帮我挡掉了无数次“把调试日志提交上去了”的尴尬。

3.3 log:查看历史提交的几种姿势

提交后想查看历史,基础用法是:

git log

默认输出很冗长,我常用的精简版本:

git log --oneline # 每行只显示提交号缩写和提交信息 git log --oneline --graph # 显示分支历史图谱 git log -n 5 # 只看最近5条

--graph配合--oneline能直观看到分支合并的历史走向,排查问题时非常有用。

3.4 git commit --amend:修改最后一次提交的正确姿势

热搜词里出现“git commit --amend怎么使用”,说明这是很多人实际想搞明白的功能。amend英文是“修订”的意思,作用就是把上一次提交替换掉。使用场景主要有两种:

场景一:提交信息写错了。

git commit --amend -m "正确提交信息"

执行后,上一次提交的信息被替换成新信息,提交号也会变化。

场景二:提交完发现漏掉了一个文件。

git add 漏掉的文件 git commit --amend --no-edit

--no-edit表示沿用原提交信息,不弹编辑器。相当于把新改动并入了上一次提交。

使用amend有一个必须注意的红线:只适用于“尚未推送到远程分支”的本地提交。如果上一次提交已经推到远端,并且别人可能已经基于它开发,此时amend会改写历史,导致其他人的仓库历史错乱。对于已经共享的提交,正确做法是再新建一次普通提交来修正,而不是amend。

3.5 撤销操作全家桶:restore、reset、reflog

撤销是另一个高频需求,但很多人搞不清三个命令的区别。我整理一个最小实用的对照表:

操作目标命令含义
丢弃工作区未暂存的改动git restore 文件名让文件回到上次暂存/提交的状态
把已暂存的文件取消暂存git restore --staged 文件名文件保留改动,但退出购物车
重置提交记录到某版本git reset --hard 提交号工作区和暂存区全部回到指定提交状态
查看所有历史操作git reflog包括已经“被撤回”的提交记录

git reset --hard很危险,因为会彻底丢弃工作区未提交的改动。执行前我用git stash或者手动复制备份的习惯已经根深蒂固。万一真的误删了,还有最后一根救命稻草:git reflog。这个命令记录了你本地所有引用变更历史,包括那些已经“消失”的提交,找到对应提交号后可恢复。我的亲身体会:reflog救回过我一个改了三天的文件,从那以后再也不敢说Git里有什么是“永久删除”的。

4. 分支操作从图片思维开始:创建、切换、合并与worktree实操

分支是Git最强大的设计,也是新手最容易翻车的地方。先打破一个思维惯性:分支不是文件夹复制,而是一枚贴在提交记录上的书签。

4.1 分支的底层认知与常用操作

回过头看1.4节说的,分支本质上是一个指向提交的指针。当前分支的指针随新提交向前移动,其他分支的指针原地不动,这就是“各改各的”这一说法的底层原理。

常用分支操作命令:

git branch # 查看本地分支,加 -a 可查看远距分支 git branch feature-login # 创建新分支 git switch feature-login # 切换到已存在的分支 git switch -c feature-login # 创建并切换到新分支(最常用的组合) git branch -d feature-login # 删除已合并的分支 git branch -D feature-login # 强制删除未合并分支,慎用

注意我写的是git switch而不是老命令git checkout。switch是Git 2.23引入的新命令,语义更清晰:切换分支用switch,恢复文件用restore,职责划分清楚,不容易“切分支却把文件搞丢”。不过老文档里到处是checkout,见到时能认识就行。

4.2 合并的两种模式:快进合并与三方合并

当你把分支合并回主干时:

git switch main git merge feature-login

如果目标分支没有新提交,Git会用“快进合并”(fast-forward),直接把main的指针挪向feature-login,历史是一条直线,合并非常干净。

如果两个分支各有过新提交,Git就会进行真正的三方合并,把两个分支的最新状态加上“共同祖先”版本做合并,生成一个全新的合并提交,历史图谱上能看到交汇点。

初学者不必把这两者创建得那么深,但要知道一件事:合并操作本身不产生网络传输,所有人都在本地完成,所以合并成本也不高,这也是Git鼓励“多开分支、频繁合并”的原因。

4.3 合并冲突:最吓人但必须学会面对的场景

两个分支都修改了同一个文件的同一行代码,Git不知道到底该保留谁的内容,就会报冲突。看到那种红色“CONFLICT”提示,第一次经历的人很容易懵,其实处理方式非常固定。

冲突发生时,用git status会看到“Unmerged paths”,业务被打断到了both modified状态。打开冲突文件,里面会出现类似这样的段落:

<<<<<<< HEAD 这是main分支的改动 ======= 这是feature-login分支的改动 >>>>>>> feature-login

处理原则极简单:把不需要的行删除,把<<<<<<<、=======、>>>>>>>这三行标记行全部删除,只保留想要的最终代码。然后:

git add 冲突文件 git commit -m "合并分支,解决冲突"

冲突不可怕,它只是Git向你抛出的一道取舍题,你自己决定留哪边就好。真正的教训是两点:第一,解决冲突时要全局搜索一遍“<<<<<<<”,以免漏掉某个没处理完的文件;第二,多人协作的公共仓库,每次干活前先拉取最新代码,可以大幅减少冲突概率。

那“我们的”和“他们的”到底分别代表谁?不同场景下含义完全不同,看<<<<<<< HEAD上面的内容不靠谱,最可靠的方式是看git status中标注的分支名,再结合提交情况判断。

4.4 git worktree:同时处理多个分支的并发利器

搜“git worktree”的人越来越多,说明很多人已经意识到“一个工作区切来切去”效率太差的问题。常规做法是:改分支A做到一半,突然要去分支B修个紧急bug,先stash当前改动,切到B,修完再切回A,pop回来。切换频繁时,光stash和pop就要花不少心思。

git worktree允许你在另一个目录同时检出另一个分支,相当于“一个仓库,多个工作区”,各分支同时打开、同时编辑、互不干扰:

git worktree add ../my-project-hotfix hotfix-branch

这会在上级目录的my-project-hotfix目录里检出一个新的工作区,分支是hotfix-branch。你可以在原目录继续改功能A,在新目录专注修紧急bug,两者都是同一个仓库的不同工作区,commit提交共享同一套历史。

我实际用下来的感受是:处理“多版本并行维护”场景时,worktree比频繁切分支高效太多。用完不用时执行git worktree remove ../my-project-hotfix清理掉即可。

5. 远程仓库、SSH密钥与认证失败排查手册

本地操作熟练之后,就要跟远程仓库打交道了。热搜词里“git配置gitee密钥”“ssh认证失败”“git免密”“git清除账号密码”全是这一块的痛点。集中串一遍。

5.1 HTTPS还是SSH:两种协议怎么选

远程仓库地址有两种形式:

  • HTTPS方式:https://github.com/xxxx/xxx.git
  • SSH方式:git@github.com:xxxx/xxx.git

两者的区别在于认证方式。HTTPS每次push都要输账号密码(或依赖凭据管理器),SSH通过密钥对认证,配置一次之后永久免密。我所有项目都优先用SSH方式,原因就是一个字:省事。尤其是长时间使用服务器或者经常写脚本拉代码的场景下,SSH免密的价值会无限放大。

5.2 生成密钥并添加到Gitee

生成密钥的命令:

ssh-keygen -t ed25519 -C "你的邮箱@example.com"

连续按三次回车,使用默认路径和空口令即可。如果平台相对古老不支持ed25519,退而求其次用ssh-keygen -t rsa -b 4096。

生成的公钥位于~/.ssh/id_ed25519.pub,用文本编辑器打开并复制全部内容。进入Gitee(或GitHub)的设置页面,找到“SSH公钥”菜单,标题随便填,把公钥内容粘贴进去保存。添加完用一条命令验证:

ssh -T git@gitee.com

首次连接时会有“Are you sure you want to continue connecting”的提示,输入yes,看到“Hi 用户名”之类的欢迎提示就说明已配置成功。

5.3 ssh认证失败的常见原因和排查顺序

项目上遇到“ssh认证失败”,报错通常是Permission denied (publickey)。按以下顺序排查,大部分问题都能定位:

第一步:确认公钥是否真的添加到平台了。这一步查操作遗漏的最多。检查公钥内容是否复制完整,有没有多复制空格或丢失尾部换行。

第二步:确认本地使用的是哪个密钥文件。如果你生成密钥时自定义过文件名,SSH默认不会读取这个文件,需要在~/.ssh/config里显式指定:

Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519

第三步:确认是否配置过多个密钥、默认用了错误的那个。机器上如果有多个私钥,SSH默认从~/.ssh/id_ed25519或~/.ssh/id_rsa里找。解决方式是把不同平台的密钥在主配置里分别指定不同的Host条目。

第四步:检查网络可达性。执行ping gitee.com或者直接浏览器访问远程仓库地址,确认网络环境能正常访问。公司内网或代理环境需要额外配置~/.ssh/config里的ProxyCommand等参数。

第五步:确认Git用户身份设置正确。git config --list看到邮箱是否跟你平台注册邮箱一致。有些平台在公钥无法识别时会退回检查邮箱,邮箱不匹配也报错。

有一个细节容易被忽略:Windows用户升级Git后,~/.ssh目录可能不在预期路径,使用ssh -v加verbose参数能看到具体读的密钥文件位置,排查时这条信息最有用。

5.4 HTTPS账号密码的缓存与清除

如果你用HTTPS克隆的项目,第一次push时会弹出窗口输入账号密码,Git会把凭据交给Windows凭据管理器保存,之后就不再询问。问题来了:平台密码改了,git push就一直报认证失败,因为还在用旧缓存。

清除缓存的姿势分版本区别:

# Windows下通过凭据管理器删 # 控制面板 → 凭据管理器 → Windows凭据 → 找到 git:https://xxx 项 → 删除 # 或使用git命令查看当前credential配置 git config --global credential.helper # macOS下直接用系统钥匙串访问程序删掉对应项

还有一个通用做法是:

git credential-manager erase

按提示输入协议和主机名,即可清除对应凭据。下次push时会重新要求输入账号密码,同时也写入新凭据。

5.5 绕开“每次输密码”的终极方案

为了不再被密码和缓存问题困扰,我的建议非常简单:一律用SSH,不用HTTPS。克隆时不要复制HTTPS地址,点仓库页面的“克隆/下载”按钮后选择SSH地址。旧仓库可以通过改remote地址切换:

git remote set-url origin git@gitee.com:用户名/仓库名.git

改完后git remote -v确认一下远程地址是否为SSH格式。再push一次,感受一下不用输password的快乐,就再也不想切回HTTPS了。

6. 高频报错与图形化工具集成:从fatal提示到IDEA、VSCode、TortoiseGit

最后把日常碰到的几个高频问题集中说一下,包括fatal: not a git repository这个让无数人搜索过的报错、IDE集成和一些额外的小工具。

6.1 “fatal: not a git repository”到底怎么回事

这个报错的完整形式是fatal: not a git repository (or any of the parent directories): .git,大意是“当前目录不是Git仓库,往上层找了也没有找到仓库”。

产生原因通常是这三种:

第一种:当前目录真的没有初始化过仓库。解决方式最简单:git init初始化即可。

第二种:你身处仓库的子目录深处,而子目录里没有.git文件夹。向上层的仓库目录执行git status即可正常。这个报错之所以带(or any of the parent directories),就是因为Git本来会自动向上层目录寻找仓库,如果一直找到根目录都没有,才报这个错。

第三种:在Git Bash里用错了工作路径。打开Git Bash后默认位置是C:/Users/你的用户名,执行cd进入实际项目目录再操作。

我的建议是先执行pwd看自己在哪个目录,再ls -a看看有没有.git目录,思路清晰了再处理,一般一分钟内能解决。

6.2 IDEA创建新项目并拉取Git仓库

IntelliJ IDEA的Git集成体验是几大IDE里做得最好的。拉取已有仓库的路径:选择File → New → Project from Version Control…,在弹出的对话框里填入Repository URL和本地目录,点击Clone即可。IDEA会自动识别SSH密钥,前提是你用的是“Git from the command line and also from 3rd-party software”那个安装选项,否则IDE可能找不到Git执行文件。

如果IDEA提示找不到Git,手动配置路径:Settings → Version Control → Git,在“Path to Git executable”里指定C:\Program Files\Git\bin\git.exe,点击Test确认版本显示正常。

IDEA里拉代码和推代码也很直观:右上角的绿色向下箭头拉取,向上箭头推送,快捷键Ctrl+T和Ctrl+Shift+K可以记一下,效率高很多。

6.3 VSCode中配置Git账号密码的思路

VSCode本身不自带Git,它只是调用系统的Git命令,所以“VSCode配置Git账号密码”这个热搜词本质上还是在配Git本身。在VSCode里第一次push时,会弹窗要求输入账号密码(凭据管理器的界面),输入后由系统保存,之后不会再问。

改密码后反复提示认证失败的处理,用前面说到的“凭据管理器删除旧凭据”方案即可。另外VSCode左下角的源代码管理面板可以直接看到所有文件变更,比敲命令直观很多,但初始化仓库、设置remote这类操作我仍然习惯在终端里完成。大概原因是前端工具的重构操作做得再好,终端里的Git命令毕竟才是最终解释标准。

6.4 TortoiseGit:Windows上的“小乌龟”

搜“git 小乌龟下载”的人通常是第一次接触Windows图形化Git。TortoiseGit是一套集成到Windows右键菜单的Git客户端,图标是一只小乌龟。它的优势在于完全不用记命令:右键就能看到“Commit...”“Pull...”“Push...”“Merge...”等等,所有操作都有图形化界面。

但实际用过一段时间我的体会是:小乌龟适合刚开始接触Git、对命令行有恐惧感的用户;一旦日常流程稍微复杂一点(rebase、worktree、批量revert),小乌龟反而束手束脚。更建议的做法是:先用小乌龟把“add、commit、push、pull、merge”这些核心动作的心智模型建立起来,然后马上转向Git Bash命令行。命令行才是走遍各大平台都通用的基本功。

6.5 顺手提一句:不要让 .git 目录暴露在“不该出现”的地方

最后提醒一点。.git目录里包含了项目全部历史记录、分支信息、甚至可能包含一些敏感信息。在部署项目、打包上传的时候,务必确认.git目录不会被一并暴露出去。正确做法是把它加入部署的忽略清单,同时切忌在公开场合随意上传包含.git目录的项目压缩包。这是很多初入行的人不太注意但在实际工作中极其重要的一条习惯。

从安装配置,到每天都要走的add/commit/push链路,再到分支合并和SSH认证,这篇文章覆盖了Git使用中最基础也最高频的完整闭环。工具终究是服务于工作的,把底层的“快照、指针、暂存区”这三件事理解透,你会发现Git的命令永远不需要背,因为你已经知道它为什么要这样设计。你先去配好SSH免密,再把每天提交前看一眼git status和git diff的习惯养成,Git这一关就算真正过了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询