Git(7.24)

一、集中式版本控制系统和分布式版本控制系统

1. 核心架构不同

  • 集中式 (CVS/SVN)必须联网。只有一个中央服务器存有完整版本库,大家干活时都得从服务器"借"书,改完再"还"回去。
  • 分布式 (Git)无需联网也能工作。每个人的电脑里都有一个完整的版本库(包含所有历史记录),相当于人手一本完整的书。

2. 安全性与容灾能力不同

  • 集中式单点故障风险高。如果中央服务器坏了或断网,所有人都没法干活,甚至可能丢失历史数据。
  • 分布式极其安全。因为每个人电脑上都有完整备份,就算某台电脑坏了,随便找别人的拷贝一份就能恢复。

3. "服务器"的角色不同

  • 集中式:服务器是必须的,它是工作的中心。
  • 分布式:所谓的"服务器"只是用来方便交换代码的中转站。即使没有它,大家也可以互相直接推送修改,只是不方便而已。

二、Git介绍

image-20260729200320120

1. 本地仓库与分支管理

  • 工作区与版本库:代码编写在“工作区”,提交后进入本地的 .git 目录(即本地版本库)。
  • 分支结构master 是默认主分支。开发者可创建 dev(开发)、test(测试)或个人分支。每个分支独立维护一套版本历史(如 v1, v2, v3),互不干扰。
  • 版本回退:若当前版本有误,可利用 Git 的版本记录功能,将分支指针回退至任意历史版本。

2. 远程协作机制

  • 中央仓库的角色:作为数据交换枢纽,存储所有成员的代码备份。它并非 Git 运行的必要条件,但却是团队协作的核心。
  • 推送 (Push):将本地特定分支的更新同步至中央仓库对应分支。支持全量或增量提交。
  • 拉取 (Pull):从中央仓库获取他人提交的最新代码,并合并至本地分支,以保持同步。

3. 冲突处理与同步流程

  • 并发修改场景:当多人同时修改同一分支(如 dev)时,遵循“先提交者优先”原则。
  • 冲突解决步骤:
    1. 若同事已先将新版本(v3)推送到中央仓库,你的推送请求会被拒绝。
    2. 你必须先执行 pull 操作,将中央仓库的 v3 拉取到本地。
    3. 在本地合并代码(解决可能存在的冲突)并提交生成新版本后,才能再次推送到中央仓库。

三、初始化设置

(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,避免与远程仓库的说明文件产生冲突。

image-20260729213700466

image-20260729213938287

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分支。

image-20260731224503603

​ (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

image-20260801153259893

①打开 readme.txt 文件进行编辑,此时文件内容是 version: 1111

②执行 git add readme.txt,把当前工作区里的 version: 1111放进了暂存区

③没有提交,而是继续在工作区修改文件,在文件末尾又加了 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 分支。
步骤:

  1. 切换到目标分支:git checkout master
  2. 执行合并命令:git merge dev

结果: master 分支就会拥有 dev 分支中的 a.txt 文件。

十四、文件冲突:

(1)冲突产生的原因
当两个分支对同一个文件的同一行内容进行了不同的修改,并尝试合并时,Git 无法自动判断该保留哪一份,就会产生冲突。

  • 自动合并(不冲突): 如果两个分支修改的是同一个文件的不同行,Git 会自动将两边的修改“穿插”合并在一起,不会报错。
  • 手动解决(冲突): 如果两个分支修改了同一行(或相邻很近的内容),Git 就会提示合并失败,需要人工介入。

(2)冲突模拟场景

  1. dev 分支拉取一个新分支 y,此时两者内容一致。

  2. dev 分支修改 a.txt 内容为 123,并执行 git add .git commit -m "123"

  3. 切换到 y 分支,修改 a.txt 内容为 112233,并执行 git add .git commit -m "112233"

  4. 尝试将 y分支合并到 dev分支:

    • 先切换到 devgit checkout dev

    • 执行合并:git merge y

    • 结果: 合并失败,提示冲突。

(3)解决冲突的步骤
当发生冲突时,IDEA 的文件图标上会出现特殊的标记(如三角号),打开文件会看到 Git 自动插入的冲突标记:

<<<<<<< HEAD
123
=======
112233
>>>>>>> y
  • <<<<<<< HEAD======= 之间是当前分支(dev)的内容。
  • =======>>>>>>> y 之间是传入分支(y)的内容。

解决过程:

  1. 手动编辑文件: 打开冲突文件,根据需求决定保留哪部分代码(可以全留、只留一边,或者手动合并)。
  2. 删除冲突标记: 必须手动删除 <<<<<<<=======>>>>>>> 这些提示符号。
  3. 标记已解决: 保存文件后,执行 git add a.txt(或 git add .)告诉 Git 冲突已解决。
  4. 提交合并: 执行 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 pushmaster

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 会克隆远程仓库的默认分支

image-20260803184006022

image-20260803184045586

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

image-20260803184250025

2. 日常开发流程

切换/创建分支
  • 原则:永远不要在 devmaster 上直接开发,必须基于它们拉取自己的功能分支。
  • 操作:
    1. 在 Git 工具窗口的找到目标分支(如 origin/dev)。
    2. 右键 -> Checkout(如果是新分支则选择 Checkout as new local branch)。
    3. 此时右下角状态栏应显示你的分支名(如 Dongan)。
提交代码 (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,这样本地分支就是自己的分支了。

image-20260803185455444

image-20260803185509638

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

image-20260803185719018

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

image-20260803185859802

选择提交后,必须写Message。

  • 提交:只管提交到本地库

  • 提交并推送:提交到本地,并推送到远端仓库

image-20260803190116709

点击提交并推送后,远端库已经是最新的了。

修改启动类注释,添加456,再选择提交

image-20260803190550284

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

image-20260803190719229

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

image-20260803190919931

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

image-20260803191013731

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

image-20260803191340159

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

image-20260803191604993

再右键Git,选择push提交。添加Message,修改了注释。再提交并推送。在push。会发生冲突。

Rebase(变基)
你把远程最新的代码拉下来,然后把你自己的修改"重新放"到最新代码的后面。这样提交历史就是一条直线,看起来很干净。但注意,它会改变你原来提交的记录。

Merge(合并)
你把远程的代码和你本地的代码合在一起,生成一个新的"合并提交"。这样能完整保留两边的开发历史,但提交记录会有分叉,看起来像树枝一样。

image-20260803192052622

image-20260803192256485

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

image-20260803192345628

可以在中间进行合并修改。解决完点击Apply即可。Marge完成之后,在左上角在重新commit and Push

重点: 哪怕冲突是因为别人改了远程代码引起的,当你打开 IDEA 这个三栏合并窗口时,所有的操作(点击接受左侧、右侧,或者在中间打字)全都是发生在你自己的电脑(本地)上的。此时,远程仓库的代码完全没有变,它还保持着那个让你报错的状态。

(2)将本地仓自己的分支提到远程仓的dev分支上

先把dev checkout,把当前分支切换到dev,再右键自己分Merge 'Dongan' into 'dev'

image-20260803194148961

image-20260803194221173

合并完成后,右键dev选择push,直接push,就是把刚才合并的内容推送到远端服务器。

(3)别人改完代码合并到dev上,我又改完代码也往dev合并,发生冲突

场景:
在远端 dev 分支上,同事修改了某行代码为 112233。同时,我在本地自己的分支(Dongan)也修改了同一行代码为 778899

解决步骤:

  1. 推送自己的分支:我先将自己本地的 Dongan 分支推送到远程(这一步通常不会冲突,因为远程 Dongan 只有我在用)。
  2. 同步 dev 分支:
    • 切换到 dev 分支,观察控制台,如果 dev 旁边有向左下的小箭头,说明远程 dev 有更新。
    • 右键 dev 选择 Pull,将同事的最新代码拉取到本地 dev
  3. 合并自己的分支到 dev:
    • 保持当前在 dev 分支,右键自己的分支(Dongan),选择 Merge 'Dongan' into 'dev'
    • 此时因为两边修改了同一行,会弹出冲突解决窗口。
  4. 解决冲突并推送:
    • 在三栏视图中解决冲突(保留 112233778899,或手动合并),点击 Apply
    • 解决后,dev 分支旁边会出现向右上小箭头,说明本地 dev 有新的合并提交。
    • 右键 dev 选择 Push,将合并后的代码推送到远程服务器。
posted on 2026-08-03 21:00  冬冬咚  阅读(8)  评论(0)    收藏  举报