1、什么是git
Git是一个开源的分布式版本控制系统,是目前世界上最先进,最流行的版本控制系统。其特点是项目越大越复杂时,协同开发者越多,越能体现出Git的高性能和高可用性。git快速和高效,一是因为它能直接记录快照,而非差异比较;二是几乎所有操作都是本地执行。
Git对象


2、git的基本使用
git可以帮助我们做很多的事情,比如代码的版本控制,分支管理等。git里面主要包含的几个概念有远程仓库,克隆,本地仓库,分支,提交,拉取,合并,推送等。远程仓库是指我们代码存储在服务器的地方,这个仓库是我们整个团队中所有人都可以访问的地方。【git工作目录下对于文件的修改 (增加、删除、更新)会存在几个状态,这些修改的状态会随着我们执行git的命令而发生变化。】

git commit:暂存区-->本地仓库
git add:工作区-->暂存区
- 克隆:从远程仓库克隆到本地的过程。本地仓库指的是我们开发人员从远程仓库克隆一份代码之后,保存在我们本地的代码,这份代码只有克隆的代码的开发人员可以看到。
- 分支:我们在开发中可能会遇到多个分支进行,比如主分支(master分支),开发分支(develop分支),但我们开发的时候,一般不在master上面进行开发,而是我们自己单独的从主分支或者开发分支中在分出来一条分支(比如test分支),然后我们就在test分支上进行开发,每个分支都有自己的代码。
- 提交:在我们的代码开发完成之后,需要将代码进行提交,提交的时候需要我们将修改的文件进行提交,并说明修改的内容。注意,此时代码提交只会提交到我们本地的仓库,远程仓库此时还不会修改。
- 拉取:开发中,同一个项目可能是多人协作开发,这个时候,我们就需要将别人修改的代码拉去下来合并到我们自己的代码中。但是如果不同的开发人员修改了统一部分代码,那么就可能发冲突,这时候我们需要解决完冲突时候,才能继续将代码进行提交。
- 合并:在上面我们自己的分支开发完成之后,没有问题之后,需要将我们的分支合并到主分支上面。
- 推送:之前的所有操作都是在我们本地进行的,远程仓库的代码并没有任何的改变,这个时候就需要我们将本地的代码推送到远程的仓库中,更新远程仓库代码。在推送的过程中,如果我们本地的代码不是最新版本的,就需要我们先将远程代码拉去下来(如果有冲突重新解决冲突,提交),然后在重新推送。

3、获取本地仓库
1)在电脑的任意位置创建一个空目录(例如test01)作为我们的本地git仓库
2)进入这个目录中,点击右键打开git bash窗口
3)执行命令git init(初始化当前目录为一个git仓库)
4)如果创建成功后可在文件夹下看到隐藏的.git目录。
4、git常用命令
1、提交步骤
git init:初始化git仓库
git status:查看文件状态
git add:文件列表追踪文件
git commit -m:提交信息,向仓库中提交代码
git log:查看提交记录
2、撤销
用暂存区中的文件覆盖工作目录中的文件: git checkout 文件名
将文件从暂存区中删除: git rm --cached 文件名
将 git 仓库中指定的更新记录恢复出来,并且覆盖暂存区和工作目录:git reset --hard commitID
3、暂时保存更改
在git中,可以暂时提取分支上所有的改动并存储,让开发人员得到一个干净的工作副本,临时转向其他工作。
使用场景:分支临时切换
存储临时改动:git stash
恢复改动:git stash pop
5、git分支常用命令
git branch 查看分支
git branch 分支名称 创建分支
git checkout 分支名称 切换分支
git merge 来源分支 合并分支 (备注:必须在master分支上才能合并develop分支)
git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)





6、查看某些状态(重点)
1、查看修改的状态(status) git status
作用:查看的修改的状态(暂存区、工作区)
2、添加工作区到暂存区(add) git add 单个文件名|通配符
作用:添加工作区一个或多个文件的修改到暂存区
3、提交暂存区到本地仓库(commit) git commit -m '注释内容'
作用:提交暂存区内容到本地仓库的当前分支
4、查看提交日志(log) git log
作用:查看提交记录

7、应用场景中常遇到的问题
1)与其他人同时修改远程仓库的同一个文件的不同部分,例如不同行代码,其他人先执行git push,然后自己再执行git pull更新后,会导致其他人对这个文件的修改覆盖自己对这个文件的修改吗。?
解答: 通常不会直接覆盖,但可能会产生合并冲突,需要开发人员手动解决。
**核心原则:**git的合并机制。Git不是简单地用"新文件"覆盖"旧文件"。
当你执行git pull时,它实际上是两个命令的组合:
- git fetch:将远程仓库的最新内容下载到本地,但不修改你的工作文件。
- git merge:尝试将远程的更改(别人提交的)和你本地的更改(你还没提交的)合并到一起。
场景推演:
假设初始文件状态为版本A:
1.你和其他人同时基于版本A开始修改:
- 你修改文件的第10-20行
- 你的同事修改了文件的第50-60行
- 你们修改的是不同的行
2.同事先推送
- 同事完成修改,提交(commit),然后执行git push
- 现在远程仓库的文件状态为版本B(包含同事对50-60行的修改)
3.你在本地提交,然后尝试拉取
- 你在本地完成了对10-20行的修改,并执行了git commit,生成了你的本地提交
- 此时,你本地的历史是:版本A->你的提交
- 远程的历史是:版本A->同事的提交
4.你执行git pull
- git fetch将远程的版本B下载下来
- git merge开始工作,它会比较三个版本
1)共同祖先:版本A
2)远程分支的头:版本B(同事的修改)
3)你当前分支的头:你的本地提交(你的修改)
- git会进行只能分析:从分析A开始,同事改了50-60行,你改了10-20行。这些修改互不干扰。
- 在这种情况下,git可以自动完成合并!它会生成一个新的合并提交,这个提交同时包含了你们两个的修改(即文件现在既有你对10-20行的改动,也有同事对50-60行的改动)。
- 此时,你的工作目录中的文件就是合并后的完美版本。没有冲突,你的修改也没有被覆盖。
什么情况下会产生冲突?
如果你们的修改有交集,git无法自动决定保留哪个,就会产生冲突。例如:
- 修改了同一行或相邻行:你对第15行做了修改,同时也对第15行做了不同的修改。
- 其中一人删除了另一个人修改的行:第修改了第15行,但同事删除了第15-20行。
- 文件结构发生复杂变化:比如同事命名了函数,而你在老函数名的地方添加了代码。
冲突发生时的表现:
1、当你执行git pull遇到冲突时,过程会暂停。Git会:
<<<<<<< HEAD
这是你本地修改的内容
=======
这是远程拉取下来的内容
>>>>>>> commit-hash-of-remote
2、你需要手动打开这些文件,检查标记之间的内容,决定保留哪一部分,或者进行融合修改。
3、修改完成后,用 git add <文件名> 标记冲突已解决,然后执行 git commit 来完成这次合并。
最佳实践方案:
|-----------|--------|---------------------------------------------------------|
| 修改情况 | 结果 | 你的操作 |
| 不同部分(无重叠) | 自动合并成功 | 直接推送git push即可。 |
| 相同部分(有重叠) | 产生合并冲突 | 1、手动解决冲突文件。 2、git add标记解决。 3、git commit完成合并。 4、git push |
工作中最佳实施方案:
-
勤拉取 :在开始工作前和提交前,都先执行一次
git pull,保持本地代码尽可能新,减少冲突范围和概率。 -
分段提交:不要一次性修改太多东西然后做一个大提交。小的、目的明确的提交更容易理解和合并。
-
沟通:如果团队在紧密协作同一个模块或文件,提前沟通可以避免很多冲突。
-
理解
pull --rebase:另一种工作流是使用git pull --rebase。它会将你的提交"变基"到远程最新提交之后,形成一条线性的历史,有时可以使历史更整洁,但原理和merge不同,需要额外学习。
2)与其他人同时修改远程仓库的同一个文件的相同部分,例如修改同一行代码。其他人先执行git push,然后自己再执行git pull更新后,会导致其他人对这个文件的修改覆盖自己对这个文件的修改吗?
解答: 你的本地修改不会被直接覆盖,但会产生合并冲突,你需要手动解决这个冲突。
场景推演
假设初始文件状态为版本A
1.你和其他人同时修改同一行:
-
文件中第15行原来是:
var x = 10; -
你将其修改为:
var x = 20; // 提高性能 -
你的同事将其修改为:
var x = 15; // 折中方案 -
你们都修改了完全相同的位置。
2.同事先推送:
- 同事提交并执行git push
- 远程仓库变为版本B(包含同事的修改)
3.你提交后拉取:
- 你在本地提交了你的修改,然后执行git pull
- git会尝试合并,但发现从版本A到版本B和从版本A到你的本地提交都修改了同一行。
4.git的应对:
- git无法自动决定应该保留谁的修改,因为这涉及到语义冲突,git无法智能判断。
- git会暂停合并过程,并在文件中标记冲突。
3)如果两个人修改的是文件夹里的不同文件呢?
解答: 完全不会覆盖,Git会非常顺利地进行合并。
场景推演
假设有一个文件夹包含两个文件:
- file1.txt
- file2.txt
1.初始状态:
- 两个文件都是版本A的一部分。
2.两人同时修改不同文件:
- 你修改了file1.txt
- 你的同事修改了file2.txt
3.同事先推送:
-
同事提交了对
file2.txt的修改,并执行git push -
远程仓库变为版本B (包含同事对
file2.txt的修改)
4.你提交后拉取
-
你在本地提交了对
file1.txt的修改 -
执行
git pull
git的合并过程
当你执行 git pull 时:
-
Git会比较三个版本:
-
共同祖先:版本A(两个文件都是原始状态)
-
远程分支头 :版本B(只有
file2.txt被修改) -
你的本地提交 :只有
file1.txt被修改
-
-
Git会分析:从版本A开始,远程修改了
file2.txt,你修改了file1.txt。 -
Git能够轻松地将这两个独立的修改自动合并 ,因为它们是完全不相交的更改。
8、总结
|------------|---------|----------|
| 修改情况 | git处理结果 | 你的操作 |
| 不同文件 | 自动合并成功 | 直接推送即可 |
| 同一个文件的不同部分 | 自动合并成功 | 直接推送即可 |
| 同一个文件的相同部分 | 产生合并冲突 | 需要手动解决冲突 |
| 文件重命名/删除冲突 | 可能产生冲突 | 可能需要手动解决 |
最佳实践建议
-
保持原子提交:每个提交只修改相关的文件,便于理解和合并。
-
拉取频率:即使修改不同文件,也建议在开始工作前和推送前先拉取最新代码。
-
沟通协调:对于大的重构(如文件重命名、移动),提前通知团队成员。
-
使用分支策略:在功能分支上工作,定期合并主分支的更新,减少冲突可能性。