文章目录
- 1.Git概述
- [2.Git VS SVN](#2.Git VS SVN)
- 3.Git本地常用命令
-
- 3.1设置、查看用户签名(config)
- 3.2初始化本地库(init)
- 3.3查看本地库状态(status)
- 3.4添加和删除文件至暂存区(add、rm)
- 3.5从暂存区提交文件至本地库(commit)
- 3.6查看版本历史
-
- [3.6.1Git log(提交内容历史)](#3.6.1Git log(提交内容历史))
- [3.6.2Git reflog(本地操作历史)](#3.6.2Git reflog(本地操作历史))
- 3.6.3核心区别总结
- [3.7版本穿梭(checkout VS reset)](#3.7版本穿梭(checkout VS reset))
- 4.Git分支操作(branch)
-
- 4.1查看分支
- 4.2创建分支(branch)
- 4.3切换分支(checkout)
-
- [4.3.1Git Stash(临时暂存)](#4.3.1Git Stash(临时暂存))
- 4.4合并分支(merge、rebase)
-
- 4.4.1Merge
- 4.4.2Rebase
- [4.4.3Merge VS Rebase](#4.4.3Merge VS Rebase)
- 4.4.4适用场景与最佳实践
- 4.5删除分支
- 5.Git远程操作
-
- 5.1创建远程仓库别名(add)
- 5.2推送本地分支到远程仓库(push)
- 5.3拉取/提取远程分支到本地仓库(fetch、pull)
-
- 5.3.1提取远程分支代码(fetch)
- 5.3.2拉取远程分支代码(pull)
- [5.3.3 Git pull和Git fetch的核心区别](#5.3.3 Git pull和Git fetch的核心区别)
- 5.4克隆远程仓库到本地(clone)
1.Git概述
1.1什么是Git
Git 是由 Linus Torvalds 于 2005 年开发的分布式版本控制系统,用于高效追踪文件变更、管理代码历史、支持多人协作开发,是目前全球最主流的版本控制工具。
1.2Git的核心设计:快照式存储
Git 不存储文件的差异变更,而是在每次提交时生成整个项目的完整快照。对于未修改的文件,仅保留指向原文件的引用,既保证了速度,又确保了数据完整性。
1.3三大核心工作区域
Git 的所有操作都围绕这三个区域流转:
- 工作区(Working Directory):电脑上能直接编辑的文件目录。
- 暂存区(Staging Area):提交前的临时缓冲区,用于整理本次要提交的内容。
- 版本库(Repository):本地仓库,保存所有提交的历史快照和元数据。
1.4基本工作流程
Git 最基础的协作流程:
-
在工作区修改文件。
-
git add:将修改添加到暂存区。 -
git commit:将暂存区内容提交到本地版本库。 -
git push:将本地提交推送到远程仓库。
2.Git VS SVN
Git(分布式)与 SVN(集中式)的核心区别源于架构设计的本质差异,并由此延伸出安全性、效率、工作流等多维度的不同。以下是清晰对比:
2.1核心架构差异
| 维度 | SVN(集中式) | Git(分布式) |
|---|---|---|
| 仓库结构 | 仅有一个中央服务器保存完整版本库 | 每个开发者本地都有完整的版本库(含全部历史) |
| 依赖关系 | 所有操作依赖中央服务器,服务器挂了全停工 | 本地可独立操作,仅同步时需与远程交互 |
| 类比 | 像 "图书馆",只有一本正本,大家只能借了改 | 像 "每人手里都有一本完整的书",自己改自己的,最后合并 |
2.2关键功能对比
-
安全性与数据备份
SVN:风险高度集中 。中央服务器磁盘损坏或数据丢失,所有历史版本可能彻底丢失(仅靠本地最新代码无法恢复历史)。
Git:极度安全。每个本地仓库都是完整备份,即使远程服务器挂了,随便找一个开发者的本地仓库就能恢复全部历史。
-
网络依赖(效率差异核心)
SVN:几乎所有操作都需联网(查看历史、提交代码、对比版本等),网络差时效率极低。
Git:90% 操作在本地完成(提交、查看历史、分支切换、代码对比等),无需联网,速度极快,仅在 "推送到远程" 或 "拉取他人代码" 时才需网络。
-
分支管理(体验差异最大)
SVN:分支是 "目录复制",创建分支慢、切换慢,合并分支时易冲突且难处理,开发者通常不敢轻易建分支。
Git:分支是 "指针移动",创建 / 切换分支仅需 0.01 秒,极其轻量,鼓励 "频繁分支、频繁合并"(如 Git Flow 工作流)。
-
工作流程灵活性
SVN:线性工作流,必须先 "更新(update)" 再 "提交(commit)",否则容易冲突,且冲突解决麻烦。
Git:非线性工作流,可本地多次提交、随意切换分支,支持 "先本地提交,后合并整理",适合复杂协作(如开源项目)。
3.Git本地常用命令
3.1设置、查看用户签名(config)
Git首次安装必须设置一下用户签名,用于区分不同操作者的身份,用户的签名信息在每次提交中都会展示。
-
设置用户签名。
git config --global user.name 用户名 git config --golbal user.email 邮箱 -
查看用户签名。
git config --global user.name git config --golbal user.email
3.2初始化本地库(init)
-
进入指定的目录后:
git init
3.3查看本地库状态(status)
git status
3.4添加和删除文件至暂存区(add、rm)
-
添加hello.txt至暂存区。
git add hello.txt -
删除暂存区中的hello.txt。
git rm --cached hello.txt
3.5从暂存区提交文件至本地库(commit)
-
从暂存区提交hello.txt至本地库。
git commit -m "日志信息" hello.txt
3.6查看版本历史
| 命令 | 核心定位 | 核心特点 |
|---|---|---|
| git log | 查看可达的提交历史 | 展示提交节点、可同步到远程 |
| git reflog | 查看本地操作引用日志 | 记录所有本地操作、仅本地有效 |
3.6.1Git log(提交内容历史)
| 命令 | 功能描述 |
|---|---|
| git log | 查看当前分支完整提交历史(分页模式) |
| git log --oneline | 简洁展示(一行一个提交,仅显示哈希前缀 + 提交信息) |
| git log -n | 仅显示最近 n 条提交(例:git log -5) |
| git log --graph | 以图形化展示分支合并历史 |
| git log --all | 查看所有分支的提交历史 |
执行
git log后终端进入less分页阅读器,退出方式:
- 核心:按 q 键(quit)直接退出(无需回车);
- 应急:按
Ctrl + C强制退出;
3.6.2Git reflog(本地操作历史)
| 命令 | 功能描述 |
|---|---|
| git reflog | 查看 HEAD 的所有本地操作记录(最常用) |
| git reflog show 分支名 | 查看指定分支的操作记录(例:git reflog show dev) |
| git reflog expire --expire=now --all | 手动清理所有 reflog 记录(谨慎使用) |
reflog仅保存在本地,不会通过git push同步到远程;默认保留 90 天未引用的记录,误操作后尽快恢复;
仅记录本地操作,其他开发者看不到你的
reflog。
3.6.3核心区别总结
| 维度 | git log | git reflog |
|---|---|---|
| 查看范围 | 仅可达的提交(未被删除 / 覆盖) | 所有本地操作(含被删除的提交) |
| 数据同步 | 可通过 push/pull 同步到远程 | 仅本地有效,不同步 |
| 核心用途 | 查看项目提交脉络、作者信息 | 恢复误操作(reset/rebase/ 删分支) |
| 数据保留 | 永久(除非手动删除提交) | 默认 90 天自动清理 |
3.7版本穿梭(checkout VS reset)
-
git checkout <版本号>:临时查看历史版本,不修改当前分支,进入 "分离头指针" 状态。 -
git reset --hard <版本号>:强制回退当前分支到指定版本,并丢弃所有后续提交和未保存的修改。- 回退到上一个版本:
git reset --hard HEAD^ - 回退到上上一个版本:
git reset --hard HEAD^ ^
- 回退到上一个版本:
-
参考示例:当前master分支的版本历史:A → B → C → D(master 指向 D)。
-
使用
git checkout B,临时查看B版本的代码,同时将HEAD 指针 指向该版本(detached HEAD),但不移动当前分支的指针(master 仍然指向 D)。A → B → C → D master ^ HEAD注意事项:
- 在分离头指针状态下可以正常查看代码、编译、测试,但是在此状态下提交代码,这些提交不会属于任何分支,当你切换回其他分支时,这些提交会被 Git 视为 "垃圾"删除。
- 如果想要在当前分支的某个版本上开发代码,可以使用
git checkout -b temp <版本号>,来创建一个基于指定版本号的新分支,顺利解决分离头指针状态下无法提交代码的问题。
-
使用
git reset --hard B,将当前分支指针 移动到指定版本,同时强制重置工作区和暂存区的内容到该版本。A → B master ^ HEAD- 工作区和暂存区的所有未提交修改会被永久删除。
- 当前分支指定版本之后的提交会被删除(短时间内可以通过Git命令恢复)。
- 误操作后的恢复方法 :如果不小心执行了错误的
git reset --hard,可以通过git reflog命令找到之前的提交哈希,然后再次执行git reset --hard <哈希值>恢复。
-
4.Git分支操作(branch)
4.1查看分支
-
查看分支名 + 最新提交哈希 + 最新提交信息。
git branch -v -
查看本地分支+关联的远程分支。
git branch -vv -
建立本地分支(master)与远程分支(origin/master)的关联关系。
git checkout master git branch -u origin/master -
查看所有分支(本地+远程)。
git branch -a -
查看远程分支。
git branch -r -
重命名本地分支。
git branch -m oldName newName
4.2创建分支(branch)
-
基于当前分支的最新提交创建一个新的分支(temp)。
git branch temp -
创建并切换到新的分支,适用于临时开发、修复和实验性任务。
-
基于当前分支的最新提交,创建并切换到新的分支(temp)。
git checkout -b temp -
基于指定分支(dev)的最新提交,创建并切换到新的分支(temp)。
git checkout -b temp dev -
基于指定版本(a1b2c3d4),创建并切换到新的分支(temp)。
git checkout -b temp a1b2c3d4
-
4.3切换分支(checkout)
-
切换分支。
git checkout 分支名- 未 add、未 commit 的修改属于工作区 / 暂存区内容,不属于任何分支。如果在这时切换分支,那么修改的内容不会被丢弃,也不会自动提交,而是会被带到目标分支。
- 切换分支前,必须保持工作区是干净的(commit或者stash),防止代码污染。
4.3.1Git Stash(临时暂存)
4.3.1.1概念介绍
- 基本介绍:用于临时寄存当前分支未提交的所有修改(工作区、暂存区改动),快速清空本地工作区,达到干净状态。
- 适用场景:代码编写到一半,需要临时切换分支、紧急改 Bug、拉取最新代码,又不想生成临时 WIP 提交。
- 核心作用:本地草稿箱,临时存代码,安全切换分支,符合大厂协作规范。
4.3.1.2常用命令
-
暂存:
-
基础暂存:默认寄存所有已修改、已暂存的内容。
git stash -
带备注暂存(工作推荐):便于区分多条暂存记录,防止遗忘。
git stash push -m "备注信息" -
包含新文件一起暂存:默认不保存未追踪的新文件,加 -u 可一并寄存。
git stash -u
-
-
查看所有暂存记录。
git stash list -
恢复暂存。
-
默认恢复最近一条,同时删除这条记录(推荐)。
git stash pop [序号] -
默认恢复最近一条,但保存暂存记录。
git stash apply [序号]
-
-
删除暂存记录
-
默认删除最近一条,可删除指定序号的记录。
git stash drop [序号] -
清空所有暂存(谨慎操作)。
git stash clear
-
4.3.1.3保存范围
| 会保存 | 默认不保存 |
|---|---|
| 已 add 加入暂存区的文件 | 未追踪的新建文件(需加 -u 参数) |
| 工作区已修改文件 | 配置在 .gitignore 中的忽略文件 |
4.3.1.4规范与注意事项
-
团队协作、大厂规范:切换分支前保持工作区干净,未完成代码优先使用
stash临时存放。 -
避免大量堆积无用
stash,定期清理,防止混淆。 -
stash 仅本地生效,不会提交、不会同步远程。
-
恢复多条
stash或跨分支恢复时,可能出现代码冲突,正常手动解决即可。
4.4合并分支(merge、rebase)
-
基本概念:把其它分支的代码合并到当前所在分支。
git merge/rebase 其他分支名 -
Merge 和 Rebase 是 Git 中两种完全不同的分支合并策略,没有绝对的好坏,只有适用场景的不同。
- Merge:保留完整历史,产生合并提交,历史分叉。
- Rebase:重写提交历史,无合并提交,历史线性。
4.4.1Merge
-
工作原理:Merge 会将两个分支的最新提交和它们最近的共同祖先进行三方合并,生成一个新的合并提交(Merge Commit),将两个分支的历史连接在一起。
-
操作步骤:将 dev分支(A-B-C)merge 到 master 分支(A-D-E):
# 1. 切换到目标分支(要合并到的分支) git checkout master # 2. 执行合并 git merge dev -
提交历史效果:
D --- E --- F master / / A --- B --- C ---/ ^ dev- 生成新的合并提交
F:这是 merge 操作最核心的特征,它有两个父提交:E(master 原最新提交)和C(dev 最新提交)。 - 所有原始提交完整保留 :
A、B、C、D、E的提交哈希和内容完全不变。 - 历史呈分叉状:可以清晰看到两个分支的完整开发轨迹和合并时间点。
- dev 分支完全不受影响 :dev 分支仍然指向提交
C,没有任何变化。 - 冲突处理 :如果
D/E和B/C修改了同一文件的同一行,Git 会在生成F时提示冲突,需要手动解决后再提交
- 生成新的合并提交
-
优点:
- 历史完整可追溯:能看到每个分支的开发轨迹和合并时间点。
- 操作安全简单:不会修改已有的提交历史,出错容易回滚。
- 冲突只解决一次:所有冲突集中在合并提交中一次性解决。
-
缺点:
- 提交历史杂乱:多人协作时会产生大量合并提交,历史线分叉严重,难以阅读。
- 排查问题困难:当出现 bug 时,大量的合并提交会增加二分查找(git bisect)的难度。
4.4.2Rebase
- 工作原理:Rebase 会找到两个分支的最近共同祖先,然后将当前分支的所有提交 "截取" 下来 ,临时保存为补丁,接着将当前分支指针移动到目标分支的最新提交上,最后将保存的补丁依次应用到这个新位置上。
简单来说:把你的提交 "挪动粘贴" 到目标分支的最新提交后面。
-
操作步骤:将 dev分支(A-B-C)rebase 到 master 分支(A-D-E):
1. 切换到要变基的分支(你的开发分支)
git checkout master
2. 执行变基
git rebase dev
-
提交历史效果:
A --- B --- C --- D' --- E' master
^
dev
- 重写 master 分支历史:没有生成新的合并提交,历史变成一条完美的直线。
- 原 master 提交被重写 :D → D'、E → E',提交内容完全不变,但提交哈希发生了改变。
- 变基过程:
- Git 先找到两个分支的共同祖先A。
- 临时保存 master 分支自A以来的所有提交(D、E)为补丁。
- 将 master 分支指针移动到 dev 的最新提交C。
- 依次将补丁D、E应用到C的后面。
- dev 分支完全不受影响:dev 分支仍然指向提交C,没有任何变化。
- 冲突处理:如果D和B/C有冲突,Git 会在应用D时暂停,解决冲突后执行git rebase --continue继续应用E;如果E也有冲突,需要再次解决。
- 如果想放弃变基,恢复到变基前的状态:
git rebase --abort。
- 优点:
- 提交历史整洁:没有多余的合并提交,历史线性,易于阅读和理解。
- 便于代码审查:PR/MR 中的提交记录清晰,每个提交都是独立的功能点。
- 便于后续操作:二分查找、回滚等操作更加简单高效。
- 缺点:
- 重写提交历史:会改变已有的提交哈希,存在一定风险。
- 冲突解决繁琐:如果有多个提交都有冲突,需要逐个提交依次解决。
- 操作相对复杂:新手容易出错,出错后回滚难度较大
4.4.3Merge VS Rebase
| 对比维度 | Merge | Rebase |
|---|---|---|
| 提交历史 | 保留完整历史,产生合并提交,历史分叉 | 重写提交历史,无合并提交,历史线性 |
| 提交哈希 | 原有提交哈希不变 | 被变基的提交哈希全部改变 |
| 冲突处理 | 一次性解决所有冲突 | 逐个提交依次解决冲突 |
| 操作安全性 | 高,不修改已有历史,出错易回滚 | 中,修改已有历史,出错回滚较难 |
| 学习成本 | 低,简单易懂 | 高,需要理解变基原理 |
| 历史可读性 | 差,大量合并提交导致历史杂乱 | 好,线性历史清晰易读 |
| 对团队的影响 | 小,不会影响其他人的本地仓库 | 大,已推送到远程的提交禁止变基 |
4.4.4适用场景与最佳实践
-
Merge使用场景:
- 合并公共主干分支 :将
dev合并到master,或者将master合并到dev。 - 多人协作的公共分支:所有团队成员都在使用的分支,必须保留完整的合并历史。
- 需要保留分支开发轨迹:当你需要明确知道某个功能是从哪个分支、在什么时间合并进来的时候。
- 合并公共主干分支 :将
-
Rebase使用场景:
- 个人功能分支同步主干代码 :将
dev的最新代码同步到你的feature分支。 - 提交 PR/MR 之前:整理你的提交历史,让代码审查更加顺畅。
- 本地未推送的提交:只在你自己的本地分支上使用,不要影响其他人
- 个人功能分支同步主干代码 :将
-
大厂通用规范:
-
公共主干分支(master/dev):永远使用 Merge。
- 保留完整的合并轨迹,便于问题追溯和回滚。
- 避免因变基导致的团队协作混乱。
-
个人功能分支:优先使用 Rebase。
- 保持提交历史整洁,便于代码审查。
- 每次拉取主干代码时使用 git pull --rebase 代替 git pull。
-
Rebase 黄金法则(绝对不能违反)**:**永远不要对已经推送到远程仓库的提交执行变基操作!这会导致其他团队成员的本地历史与远程不一致,引发严重的协作混乱。。
-
4.5删除分支
不能删除当前分支,只能删除其它分支。及时清理不再需要的分支以保持仓库整洁!
-
安全删除分支(已合并才允许删除)。
git branch -d 分支名 -
强制删除分支(无论是否合并)。
git branch -D 分支名
5.Git远程操作
5.1创建远程仓库别名(add)
-
创建远程仓库别名。
git remote add 远程仓库别名 <url>- 远程仓库别名默认为
origin,取决于远端服务器设置。 - 远程仓库地址,从远端服务器获取此url。
- 远程仓库别名默认为
-
查看所有远程地址别名。
git remote -v
5.2推送本地分支到远程仓库(push)
-
完整命令语法。
git push [-f][-u/--set-upstream] [url/远程仓库别名 [本地分支名称][:远程分支名称]]-f表示强制覆盖。-u表示建立起本地分支与远程分支的关联关系,后续推送操作可以省略远程仓库名称 和分支名称 ,使用git push即可推送当前所在的本地分支的最新提交 至关联的远程分支。- 一个本地分支只能关联一个远程分支,多次执行
-u会更新关联关系。
-
远程分支与本地分支同名时可以只写一次分支名称(!!!推荐)。
git push -u origin 本地分支名称假设推送本地
master分支到远程的origin/master分支。远程没有master分支(第一次推送) 远程已有master分支 1.自动在远程 origin仓库新建一个master分支1.不会新建分支,直接将本地 master的提交推送到远程已有的master分支2.将本地 master分支的所有提交完整推送到远程2.自动建立本地 master与远程origin/master的上游关联关系3.自动建立本地 master与远程origin/master的上游关联关系3.如果有冲突,会提示先拉取远程代码解决冲突后再推送
5.3拉取/提取远程分支到本地仓库(fetch、pull)
5.3.1提取远程分支代码(fetch)
-
提取指定远程分支的最新提交,只更新对应的远程跟踪分支,不碰任何本地代码和分支。
git fetch [url/远程仓库别名 [远程分支名称]]git fetch origin dev的执行效果:- 提取远程
origin仓库dev分支的最新提交。 - 更新本地的远程跟踪分支
origin/dev(这是 Git 自动维护的,名称永远是 origin/远程分支名,不能自定义)。 - 不创建、不修改任何普通本地分支。
- 提取远程
-
fetch常用写法:提取所有远程分支的最新提交(!!!推荐)。
git fetch [url/远程仓库] -
fetch后的后续操作:拉取完成后,需要手动将远程更新合并到本地分支。
git checkout dev //切换到本地dev分支 # 方式1:合并方式(推荐公共分支使用) git merge origin/dev # 方式2:变基方式(推荐个人分支使用) git rebase origin/dev
5.3.2拉取远程分支代码(pull)
-
自动合并远程代码到当前本地分支。
git pull [--rebase] [url/远程仓库别名 [远程分支名称][:本地分支名称]]-rebase:使用 变基(Rebase)方式合并远程代码,替代默认的合并(Merge) 方式,不会产生额外的合并提交记录。- 若本地分支已与远程分支建立关联关系,后续拉取操作可以省略远程仓库名称 和分支名称 ,使用
git pull即可拉取当前所在的本地分支所关联的远程分支的最新提交。
-
远程分支与本地分支同名时可以只写一次分支名称(!!!推荐)。
git pull origin 远程分支名称
5.3.3 Git pull和Git fetch的核心区别
| 操作 | 执行内容 | 对本地分支的影响 | 适用场景 |
|---|---|---|---|
git pull |
git fetch + git merge(或git rebase) |
自动合并远程代码到本地当前分支 | 确定要将远程更新合并到本地时使用 |
git fetch |
仅拉取远程更新,不合并 | 仅更新远程跟踪分支,本地工作区不变 | 只想查看远程更新,暂时不想合并时使用 |
5.4克隆远程仓库到本地(clone)
-
克隆远程仓库到本地。
git clone <url> [本地目录] //克隆到指定名称的本地目录,而不是默认的仓库名 git clone -b 远程分支名 <url> //只克隆指定分支,不下载其他分支的历史 git clone --depth 1 <url> //浅克隆,只下载最新一次提交,速度快(不包含完整历史) -
克隆的完整执行步骤:
- 创建本地目录:以远程仓库名命名,在当前路径下新建一个空目录。
- 初始化本地仓库:在该目录中执行 git init,创建 .git 隐藏文件夹。
- 添加远程仓库别名:自动为远程仓库添加默认别名 origin(等价于 git remote add origin )。
- 拉取完整远程代码:下载远程仓库所有分支的所有提交历史和代码。
- 创建所有远程跟踪分支:在本地生成 origin/master、origin/dev 等所有远程分支的本地镜像。
- 自动创建并切换到默认分支:创建与远程默认分支(通常是 main 或 master)同名的本地分支,并自动切换到该分支。
- 自动建立上游关联关系:将本地默认分支与远程默认分支绑定(等价于 git branch -u origin/master)。
-
注意事项:
- git clone 只会为远程仓库的「默认分支」(通常是 main 或 master)自动创建本地分支并建立上游关联。其他所有远程分支,Git 只会在本地生成远程跟踪分支(如 origin/dev),不会自动创建对应的本地分支,更不会建立关联。
- 当你执行 git checkout 分支名 时,如果本地没有这个分支,但远程有同名分支,Git 会自动:
- 创建同名本地分支,自动切换到该分支。
- 自动建立与远程分支的上游关联。