Git(7.24)
一、集中式版本控制系统和分布式版本控制系统
1. 核心架构不同
- 集中式 (CVS/SVN):必须联网。只有一个中央服务器存有完整版本库,大家干活时都得从服务器"借"书,改完再"还"回去。
- 分布式 (Git):无需联网也能工作。每个人的电脑里都有一个完整的版本库(包含所有历史记录),相当于人手一本完整的书。
2. 安全性与容灾能力不同
- 集中式:单点故障风险高。如果中央服务器坏了或断网,所有人都没法干活,甚至可能丢失历史数据。
- 分布式:极其安全。因为每个人电脑上都有完整备份,就算某台电脑坏了,随便找别人的拷贝一份就能恢复。
3. "服务器"的角色不同
- 集中式:服务器是必须的,它是工作的中心。
- 分布式:所谓的"服务器"只是用来方便交换代码的中转站。即使没有它,大家也可以互相直接推送修改,只是不方便而已。
二、Git介绍

1. 本地仓库与分支管理
- 工作区与版本库:代码编写在“工作区”,提交后进入本地的
.git目录(即本地版本库)。 - 分支结构:
master是默认主分支。开发者可创建dev(开发)、test(测试)或个人分支。每个分支独立维护一套版本历史(如 v1, v2, v3),互不干扰。 - 版本回退:若当前版本有误,可利用 Git 的版本记录功能,将分支指针回退至任意历史版本。
2. 远程协作机制
- 中央仓库的角色:作为数据交换枢纽,存储所有成员的代码备份。它并非 Git 运行的必要条件,但却是团队协作的核心。
- 推送 (Push):将本地特定分支的更新同步至中央仓库对应分支。支持全量或增量提交。
- 拉取 (Pull):从中央仓库获取他人提交的最新代码,并合并至本地分支,以保持同步。
3. 冲突处理与同步流程
- 并发修改场景:当多人同时修改同一分支(如
dev)时,遵循“先提交者优先”原则。 - 冲突解决步骤:
- 若同事已先将新版本(v3)推送到中央仓库,你的推送请求会被拒绝。
- 你必须先执行
pull操作,将中央仓库的 v3 拉取到本地。 - 在本地合并代码(解决可能存在的冲突)并提交生成新版本后,才能再次推送到中央仓库。
三、初始化设置
(1)首先需要在电脑上创建一个git的工作目录。
- 新建文件夹:创建并命名项目目录(如
car)。 - 启动终端:进入该文件夹,右键选择 Git Bash Here,即可在命令行中操作 Git。
(2)Git 提交需配置名字和 Email 标识身份。
--global:全局生效(本机通用),执行后会覆盖旧的全局配置。- 不加
--global:仅当前仓库生效(适合区分工作/个人)。
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
四、初始化仓库
在当前目录下执行 git init,生成隐藏的 .git 文件夹即代表初始化成功。
.git 文件夹存储了所有版本历史,切勿删除。
git init
五、将项目代码放在git目录中,提交到本地
1. 准备项目代码
将项目代码拷贝到 Git 仓库目录(如 car)中。拷贝前建议先清理不必要的文件,避免冗余和冲突:
- 后端项目:执行 Maven 的
clean命令清理target文件夹。 - 前端项目:删除
node_modules文件夹(依赖包后续可通过命令重新安装)。 - 通用文件:删除默认的
README.md,避免与远程仓库的说明文件产生冲突。


2. 提交到本地仓库
Git 的本地提交流程分为两步,先将文件加入暂存区(Index),再提交到本地版本库(Repository):
-
第一步:添加到暂存区
执行git add .,将当前目录下的所有修改和新增文件加入暂存区(.代表当前路径下的所有内容)。git add . -
第二步:提交到本地版本库
执行git commit并附带提交信息,将暂存区的内容正式保存到本地版本库。git commit -m "创建了car-o2o项目"
只要 .git 文件夹存在,代码就安全地保存在本地版本库中,不会丢失。
拓展:
1、为什么 Git添加文件需要 add,commit 一共两步呢?因为 commit 可以一次提交很多文件,所以你可以多次 add 不同的文件,比如:
git add file1.txt
git add file2.txt file3.txt
git add . 当前文件夹下所有文件
git commit -m "add 3 files."
2、工作区和暂存区
在git中进行 crud 操作时都需要执行 git add 文件这个操作,底层操作将操作文件添加一个叫缓存区区域中缓存,当操作完毕之后,使用 git commit 操作,进行统一提交,将编辑文件统一同步版本中。
-
工作区:当前目录除了
.git,剩下都叫工作区。 -
暂存区:即缓存区,位于
.git下的index中。 -
本地版本库:位于
.git下的objects中。
git add . 先提交到缓冲区;git commit 到本地版本库中。
六、查看版本库状态
实际上是查看工作区和版本库里东西的状态。
-
若工作区和版本库完全一致,执行命令后为白色。
-
若修改工作区的内容后,没提缓存,执行命令后为红色。
-
若修改工作区内容后,提了缓存,但没提交到版本库,执行命令后为绿色。
git status # 查看当前git版本库的状态(查看缓存区中的文件内容)
七、提交日志
(1)git log 默认只查看当前分支的提交日志。
git log
(2)最新提交日志中,(HEAD -> master)HEAD表示当前的版本,master表示当前的分支是master分支。

(3)这条黄色的是每次提交的id。
为什么commit id要使用这么长一串字符而不是数字?
当两个人同时在一个代码上工作时候,分别往各自的本地的版本库提交时,相同的提交号对应着不同的修改,如果使用 1,2,3 这样的数字不能保证唯一性,所以 Git 使用 SHA-1 算法产生唯一标识符,保证全球唯一。
比如程序员甲和乙负责共同开发一个聊天软件,使用 Git 来版本控制。 Git 是分布式版本控制,每个人都有一个版本库。如果 Git 版本控制用 1,2,3 这样的数字来生成版本号,那么程序员甲和乙代码合并的时候就会出现问题。版本1到底是谁的?
SVN 是集中式的版本控制,只有一个版本库,所以版本号可以从 1,2,3 开始。 Git 是分布式版本控
制,每个人都有一个版本库,所以不能从 1,2,3 开始。
(4)git log 命令显示从最近到最远的提交日志,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:
git log --pretty=oneline
八、查看差异
-
修改代码后,但没提缓存,执行命令后会显示修改了哪些代码。
-
提缓存后,执行命令后,就显示无差异。
也就是说修改了代码后,只要提到缓存了,虽然没提到版本库,它也认为是一致的。
git diff # 查看不同版本之间的文件差异
九、版本回退
1.想要把当前版本回退到上一个版本
HEAD,表示退一个版本。退两个版本写HEAD^,以此类推。HEAD~100,回退100个版本。
当使用 git reset --hard HEAD^ 回退到上一个版本(比如从版本3回到版本2)后,Git 会把“当前分支指针”移到版本2。此时,如果再输入 git log,确实只能看到版本2及以前的记录,版本3就像“消失”了一样。
回退后版本没丢,只是 git log 看不到了。用 git reflog 找到那个版本的哈希值,再执行 git reset --hard <哈希值> 就能瞬间回去。
git reset --hard HEAD^
2.回到指定版本
git reset --hard <commit id>
十、管理修改
操作方式1:
第一次修改 -> git add -> 第二次修改 -> git commit

①打开 readme.txt 文件进行编辑,此时文件内容是 version: 1 和 111。
②执行 git add readme.txt,把当前工作区里的 version: 1 和 111放进了暂存区。
③没有提交,而是继续在工作区修改文件,在文件末尾又加了 222。
状态对比:
- 工作区:变成了
version: 1+111+222。 - 暂存区:依然是
version: 1+111
④执行 git commit -m "提交说明",Git 把暂存区的内容存入了版本库。
最终结局:执行 commit 后,版本库中生成的快照仅包含 111。红色的 222 依然保留在工作区中,处于已修改但未暂存的状态。它存在于你的硬盘上,但尚未被纳入 Git 的版本控制历史。
总结:git commit 只提交 git add 时的状态;add 之后在工作区做的修改,如果不重新 add,是不会被提交的。
操作方式2:推荐使用
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
PS:建议在每次 commit 之前先检查是否有文件没有被 add
十一、撤销修改
(1)git checkout -- filename 可以丢弃工作区的修改:-- 后面是一个空格
git checkout -- filename
(2)命令 git checkout -- readme.txt 意思就是,把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:
一: readme.txt 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
二: readme.txt 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总结:
git checkout -- file 这个命令,本质上是用暂存区的内容去覆盖工作区。
注意:
git checkout -- file 命令中的 -- 很重要,没有 -- ,就变成了“切换到另一个分支”的命令。
十二、删除文件
(1)删除文件的方式:
方式一:直接在文件管理器中删除,或使用系统的 rm 命令删除。
方式二:使用 Git 专用的 git rm 命令删除。
git rm test.txt
(2)删除文件后,Git 会检测到工作区和版本库不一致。可以通过git status 命令查看哪些文件被删除了。
(3)分情况添加到暂存区:
- 方式一(文件管理器 /
rm命令): 删除后,需要手动执行git add .(或git add 文件名)将删除操作添加到暂存区。 - 方式二(
git rm命令): 不需要手动添加,因为git rm已经自动完成了“删除文件”和“添加到暂存区”两个动作。
(4)提交到版本库,git commit -m "删除了test.txt"
十三、分支管理
(1)分支的基本概念与工作流
- 默认分支: 初始化仓库时默认创建
master分支。 - 常见工作流:
master:作为上线版本,保持稳定。dev:从master拉取,用于日常开发。test:从dev拉取,用于测试。测试通过后合并回master。
(2)分支相关命令
- 查看分支:
git branch - 创建分支:
git branch 新分支名(从当前分支生成,内容一致) - 切换分支:
git checkout 分支名 - 创建并切换分支:
git checkout -b 新分支名 - 删除分支:
git branch -d 分支名(注意:不能在当前分支删除自己,需先切换到其他分支) - 合并分支:
git merge 分支名(将指定分支合并到当前所在分支)
(3)合并分支示例
场景: 在 dev 分支添加了 a.txt,需要将其合并到 master 分支。
步骤:
- 切换到目标分支:
git checkout master - 执行合并命令:
git merge dev
结果: master 分支就会拥有 dev 分支中的 a.txt 文件。
十四、文件冲突:
(1)冲突产生的原因
当两个分支对同一个文件的同一行内容进行了不同的修改,并尝试合并时,Git 无法自动判断该保留哪一份,就会产生冲突。
- 自动合并(不冲突): 如果两个分支修改的是同一个文件的不同行,Git 会自动将两边的修改“穿插”合并在一起,不会报错。
- 手动解决(冲突): 如果两个分支修改了同一行(或相邻很近的内容),Git 就会提示合并失败,需要人工介入。
(2)冲突模拟场景
-
从
dev分支拉取一个新分支y,此时两者内容一致。 -
在
dev分支修改a.txt内容为123,并执行git add .和git commit -m "123"。 -
切换到
y分支,修改a.txt内容为112233,并执行git add .和git commit -m "112233"。 -
尝试将 y分支合并到 dev分支:
-
先切换到
dev:git checkout dev -
执行合并:
git merge y -
结果: 合并失败,提示冲突。
-
(3)解决冲突的步骤
当发生冲突时,IDEA 的文件图标上会出现特殊的标记(如三角号),打开文件会看到 Git 自动插入的冲突标记:
<<<<<<< HEAD
123
=======
112233
>>>>>>> y
<<<<<<< HEAD到=======之间是当前分支(dev)的内容。=======到>>>>>>> y之间是传入分支(y)的内容。
解决过程:
- 手动编辑文件: 打开冲突文件,根据需求决定保留哪部分代码(可以全留、只留一边,或者手动合并)。
- 删除冲突标记: 必须手动删除
<<<<<<<、=======和>>>>>>>这些提示符号。 - 标记已解决: 保存文件后,执行
git add a.txt(或git add .)告诉 Git 冲突已解决。 - 提交合并: 执行
git commit -m "解决冲突"完成合并。
十五、远程仓库(Gitee)
简易的命令行入门教程:
Git 全局设置:
git config --global user.name "Dongan"
git config --global user.email "2486982615@qq.com"
创建 git 仓库:
mkdir car
cd car
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/dongan1/car.git(为本地仓库添加一个远程仓库的地址)
git push -u origin "master"(将本地 master 分支的代码推送到名为 origin 的远程仓库)
已有仓库?
cd existing_git_repo(进入一个已经通过 git init 初始化过的本地项目文件夹)
git remote add origin https://gitee.com/dongan1/car.git
git push -u origin "master"
====
git pull --rebase origin master (从远程 origin 仓库的 master 分支拉取最新代码,并与本地代码合并。)
为什么不能直接从 dev 推送到远程 master?
1. 技术层面:Git 本身不报错,但很危险
- 执行
git push origin dev:master时,Git 会忠实执行。 - 如果远程
master没有保护规则,你的代码会直接覆盖远程历史,极易导致别人的代码“消失”。 - 如果远程
master有你本地没有的提交,Git 会拒绝推送并提示先git pull。
2. 协作层面:严重违反团队规范
master分支代表随时可上线的稳定代码,是团队的“红线”。- 公司通常会在 Gitee/GitHub 等平台设置分支保护规则,核心包括:
- 禁止强制推送 (Force Push):防止历史被恶意覆盖。
- 禁止直接推送 (Direct Push):任何人不能直接
git push到master。
3. 正确的团队协作流程
- 开发:在自己的
dev分支上完成开发。 - 推送:将
dev分支推送到远程(git push origin dev)。 - 发起请求:在 Gitee 上发起 Pull Request (PR) 或 Merge Request (MR),申请将
dev合并到master。 - 代码审查 (Code Review):项目经理或同事审查代码。
- 合并:审查通过后,由有权限的人点击“合并”按钮,代码才正式进入
master。
一句话总结:
平时开发只推送到远程对应的功能分支(如 dev),想合入 master 必须走 PR/MR 流程,绝对不能直接 push。
十六、IDEA操作Git
1. 项目初始化与分支同步
克隆项目
- 操作:打开 IDEA -> 克隆仓库->输入 Gitee/GitHub URL。
- 说明:默认情况下,Git 会克隆远程仓库的默认分支。


获取远程新分支 (Fetch)
- 场景:刚克隆完代码,或者同事新建了分支,但你的本地列表里看不到。
- 操作:点击左下角
Git图标 -> 点击刷新按钮(或菜单栏Git->Fetch)。 - 原理:
Fetch只是把远程的“目录清单”下载下来,不会修改你本地的代码文件。

2. 日常开发流程
切换/创建分支
- 原则:永远不要在
dev或master上直接开发,必须基于它们拉取自己的功能分支。 - 操作:
- 在 Git 工具窗口的找到目标分支(如
origin/dev)。 - 右键 ->
Checkout(如果是新分支则选择Checkout as new local branch)。 - 此时右下角状态栏应显示你的分支名(如
Dongan)。
- 在 Git 工具窗口的找到目标分支(如
提交代码 (Commit & Push)
- 修改文件:修改代码后,文件名变蓝(表示已修改未暂存)。
- 提交方式 A(推荐):
- 右键文件 ->
Git->Commit File...。 - 填写 Message -> 勾选
Before Commit中的检查项 -> 点击Commit and Push。 - 作用:一次性完成“暂存(Add)”、“提交到本地(Commit)”和“推送到远程(Push)”。
- 右键文件 ->
- 提交方式 B(分步):
- 如果已经点了
Commit但没推,或者只想推送已提交的记录: - 右键文件 ->
Git->Push。 - 注意:如果本地没有新的 Commit 记录,
Push选项可能是灰色的或提示 nothing to push。
- 如果已经点了
3.解决冲突
(1)将本地仓自己的分支提到远程仓自己的分支上
正常情况下,需要先从默认分支拉取一个自己的分支,在自己分支上进行开发。
现在本地是dev分支,可以在远程选择自己的分支,右键Checkout,这样本地分支就是自己的分支了。


在本地分支的主启动类上添加123,可以看到该类变成了蓝色。

右键该类,选择Git。IDEA中可以直接提交,他会自动先add。不必先add,再commit了。

选择提交后,必须写Message。
-
提交:只管提交到本地库
-
提交并推送:提交到本地,并推送到远端仓库

点击提交并推送后,远端库已经是最新的了。
修改启动类注释,添加456,再选择提交。

现在是远端库没有456,但是本地已经改了,此时本地库是新的,没有更改。

点击提交并推送会发现点不了,因为本地没有文件变化(之前点击提交到本地库了,此时是最新状态),所以不能在这里提交了,有一个单独的提交,右键该类选择Push。

在选择push,就提交到远端仓库了。

模拟远端仓库出现冲突,在主启动类注释添加666。

在远端仓库编辑启动类注释添加111,再提交。

再右键Git,选择push提交。添加Message,修改了注释。再提交并推送。在push。会发生冲突。
Rebase(变基)
你把远程最新的代码拉下来,然后把你自己的修改"重新放"到最新代码的后面。这样提交历史就是一条直线,看起来很干净。但注意,它会改变你原来提交的记录。
Merge(合并)
你把远程的代码和你本地的代码合在一起,生成一个新的"合并提交"。这样能完整保留两边的开发历史,但提交记录会有分叉,看起来像树枝一样。


点击合并,左边是本地的,右边是服务器的,中间是合并完的。

可以在中间进行合并修改。解决完点击Apply即可。Marge完成之后,在左上角在重新commit and Push。
重点: 哪怕冲突是因为别人改了远程代码引起的,当你打开 IDEA 这个三栏合并窗口时,所有的操作(点击接受左侧、右侧,或者在中间打字)全都是发生在你自己的电脑(本地)上的。此时,远程仓库的代码完全没有变,它还保持着那个让你报错的状态。
(2)将本地仓自己的分支提到远程仓的dev分支上
先把dev checkout,把当前分支切换到dev,再右键自己分Merge 'Dongan' into 'dev'


合并完成后,右键dev选择push,直接push,就是把刚才合并的内容推送到远端服务器。
(3)别人改完代码合并到dev上,我又改完代码也往dev合并,发生冲突
场景:
在远端 dev 分支上,同事修改了某行代码为 112233。同时,我在本地自己的分支(Dongan)也修改了同一行代码为 778899。
解决步骤:
- 推送自己的分支:我先将自己本地的
Dongan分支推送到远程(这一步通常不会冲突,因为远程Dongan只有我在用)。 - 同步 dev 分支:
- 切换到
dev分支,观察控制台,如果dev旁边有向左下的小箭头,说明远程dev有更新。 - 右键
dev选择Pull,将同事的最新代码拉取到本地dev。
- 切换到
- 合并自己的分支到 dev:
- 保持当前在
dev分支,右键自己的分支(Dongan),选择Merge 'Dongan' into 'dev'。 - 此时因为两边修改了同一行,会弹出冲突解决窗口。
- 保持当前在
- 解决冲突并推送:
- 在三栏视图中解决冲突(保留
112233或778899,或手动合并),点击Apply。 - 解决后,
dev分支旁边会出现向右上小箭头,说明本地dev有新的合并提交。 - 右键
dev选择Push,将合并后的代码推送到远程服务器。
- 在三栏视图中解决冲突(保留
浙公网安备 33010602011771号