前言 📝 推荐给大家一个学习玩耍Git的网址:learngitbranch
1. 为什么要用Git?
1.1 Git能干什么呢?
用简单的一句话介绍Git,它是一个版本控制工具。
举个简单的例子: 当我们在写一个毕业论文的时候,可能会修改很多次。当我初版写完的时候我标记为V1,然后老师让我更改一些内容。我会保留一下当前的V1版本,然后将论文复制出来一份进行更改,更改之后称之为V2。当然这个复制黏贴并不是很好的解决方案。如果有一天,我想和我的朋友同时编辑论文呢?后来有了一个集中式版本控制工具svn
,可以想象有一个云存储着论文,我和我的小伙伴都在云中拉取最新的论文,然后更改完之后推送到云上。但是墨迹了半天,你说的Git到底是什么呢?
后来,Git出现了。Git
是分布式版本控制工具,Git可以让你和你的小伙伴都可以在本地存储版本,最后在都推送到远程仓库中,也就是云上。
1.2 Git的好处
我记着当时一个音乐播放软件更新了新的功能,但是当小编更新了播放器之后,在mac系统中出现了一个很大的bug。当我点击音乐的时候无法播放,页面直接卡住了。。。一个音乐播放器竟然没有办法播放音乐了。大家就在群中反馈给了音乐播放器的客户人员。小编发现新的功能已经取消了,但是bug不存在了。该播放器官方为了挽留住这么多可爱的用户,他们的第一时间并不是解决bug。已经而是先将代码进行了回滚,然后在去解决bug。当时官方还和小编要了本地的log日志。
这就体现出Git的好处了,管理代码的版本信息,能够及时解决线上出现的问题。
2. Git基操
2.1 Git初始化
把Git想象成让你害怕的班主任,你的班主任要想管理你,必须先进入到你的班级里面。Git也是同样的操作,要想让Git管理项目,需要先进入到对应的项目目录。然后初始化Git。
- 开发项目代码
html
<ul>
<li>第一次写项目,称之为V1</li>
</ul>
- 初始化Git
bash
git init
{% note warning %} git的命令路径一定要和项目路径相对应 {% endnote %}
2.2 使用Git管理项目文件
bash
# 检测当前管理目录下面的文件状态 - 文件是红色的说明还没有被管理
git status
bash
# 将index.html文件添加到git管理 - 被git管理的文件,在查看状态的时候文件颜色会变成绿色的
git add index.html
# 将所有文件都添加到git管理
git add .
2.3 生成版本
bash
# 生成一个本地版本
git commit -m '描述信息'
查看文件状态-发现什么都没有了,说明我们的所有文件都已经被Git管理起来并生成了一个版本
2.4 修改项目文件
diff
<ul>
<li>第一次写项目,称之为V1</li>
+ <li>第二次写项目,称之为V2</li>
</ul>
bash
# 查看文件状态
git status
Git检测到了文件的修改
然后在继续生成一个新的版本
bash
git add index.html
git commit -m 'v2'
2.5 查看版本记录
bash
git log
2.6 Git三大区域
为什么会有三大区域呢?工作区我能理解,就是我们写代码的地方;版本区我们也理解就是我们生成的管控版本。那为什么要有暂存区呢?这个就好比去离婚,暂存区就是离婚时给你的三十天冷静期。让你冷静思考一下看看有没有错误。
2.7 版本库回滚到工作区
我们先提交一个新的版本
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
+ <li>第三次写项目,称之为V3</li>
</ul>
bash
git add index.html
git commit -m 'v3'
我们现在不想要v3
版本了,我想回滚到v2
版本
bash
git reset --hard [hash]
git reset --hard ad5ea09f408
回滚之后查看我们的代码
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
- <li>第三次写项目,称之为V3</li>
</ul>
这是从我们的版本库中回滚代码,使代码变回了v2版本的样子。
bash
# 查看版本
git log
2.8 工作区回滚到版本库
我们从v3
回滚到了v2
, 如果说我要是不能再回滚回v3
,那我岂不得哭死。我v3
版本的代码不能丢啊。这一点Git是可以实现的。
bash
# 查看更详细的日志
git reflog
我们可以看到v3
版本的版本号
bash
git reset --hard c24613e
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
+ <li>第三次写项目,称之为V3</li>
</ul>
我们的代码又回到了v3
版本
3. Git分支
上面看我们的版本是不是特别像一个树的主干。
我们基于v3
创建了v4
和v5
分支,最后将两个分支合并,生成新的版本v6
3.1 切换分支
如果线上的代码出现了bug,如何进行紧急修复?我们在主分支上切换到一个新的分支,写新的功能。如果线上环境出现了bug,我们可以切回主分支。在基于主分支创建一个fixbug
分支。等到bug修改好之后,我们在合并的主分支上并上线。然后我们继续切回我们写新功能的分支上,继续开发新功能。
bash
# 查看分支
git branch
# 创建分支
git branch 分支名称
# 切换分支
git checkout 分支名称
# 创建并切换分支
git checkout -b 分支名称
创建并切换完成之后,我们在更改一下代码
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
<li>第三次写项目,称之为V3</li>
+ <li>第四次写项目,该项目处于dev分支,基于V3版本,称之为V3V4</li>
</ul>
继续老套路,提交新的版本
bash
git add index.html
git commit -m 'v3v4'
这个时候我们的线上环境出现了问题,我们需要切换回我们的master,也就是v3的状态
bash
git checkout master
创建修复bug的分支
bash
git checkout -b fixBug
目前的代码更改处于fixBug分支,代码并没有同步到master分支,我们需要将代码合并到master分支
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
<li>第三次写项目,称之为V3</li>
+ <li>第五次写项目,切换到fixBug分支,修复master上的bug,称之为V3V5</li>
</ul>
3.2 merge合并
当我们在fixBug
分支写完代码之后,我们再次切换回master
分支。然后执行merge
命令将修改的bug合并到当前分支。
bash
# 切换到要将代码合并到的分支
git checkout master
# 合并代码
git merge fixBug
我们在git log
一下,查看一下我们现在主分支的情况:
可以看到我们修复的bug v3v5
已经合并到主分支了,我们的v3v4
版本代表我们正在开发,并且没有开发完成的版本,并不会出现在我们的线上环境master
分支上。
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
<li>第三次写项目,称之为V3</li>
+ <li>第四次写项目,该项目处于dev分支,基于V3版本,称之为V3V4</li>
</ul>
欧克,bug修改完了,我们可以继续回到dev
分支,开发我们的新功能。
bash
git checkout dev
同理,我们修复的bug v3v5
也不会出现在我们的dev
分支上,分支之间是相互隔离的。
dev分支上新的功能:
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
<li>第三次写项目,称之为V3</li>
<li>第四次写项目,该项目处于dev分支,基于V3版本,称之为V3V4</li>
+ <li>第六次写项目,该项目处于dev分支,基于V3版本,新功能开发完成,称之为V3V6</li>
</ul>
新功能开发完成,让我们一口气提交新的版本,并合并到主分支
bash
git add index.html
git commit -m 'v3v6'
git checkout master
# 合并分支
git merge dev
由于我们修改bug和开发新项目,修改了同一行的代码。所以导致我们在合并分支的时候产生了冲突。产生冲突之后,我们找到对应的文件,手动解决冲突。解决完冲突之后,在提交新的版本。
bash
# 手动解决冲突之后
git add index.html
git commit -m 'v7'
最后我们master分支的代码(修复bug和我们的新功能全部都存在了):
diff
<ul>
<li>第一次写项目,称之为V1</li>
<li>第二次写项目,称之为V2</li>
<li>第三次写项目,称之为V3</li>
+ <li>第四次写项目,该项目处于dev分支,基于V3版本,称之为V3V4</li>
+ <li>第五次写项目,切换到fixBug分支,修复master上的bug,称之为V3V5</li>
+ <li>第六次写项目,该项目处于dev分支,基于V3版本,新功能开发完成,称之为V3V6</li>
</ul>
3.3 删除分支
我们的fixBug
分支已经不用了,我们需要删除该分支
bash
git branch -d fixBug
4. git rebase 变基
使提交git记录变得简洁
4.1 git rebase的第一种使用场景
假如说有一个非常复杂的功能,你需要提交好几次的git记录,才能写好。但是这些记录都是没有太大意义的,我们可以将这些记录合并。
这几条记录太多了,我觉得不太好。所以可以使用rebase
合并一下。
bash
# 将最新的和版本号之间的记录进行合并
git rebase -i 版本号
# 从最新的记录开始,找最近的三条进行合并
git rebase -i HEAD~3
当我们输入完命令之后,会弹出一个操作窗口:
将记录前面的改成s
,代表我们要将记录合并到上一个版本。保存之后,继续弹出一个弹框,让我们修改合并之后提交的信息。
4.2 git rebase的第二种使用场景
在我们合并分支的时候,一般都会有一个线的。我们可以使用命令查看一下图形化。
bash
git log --oneline --decorate --graph
其实通过图形化可以看到,当我们将dev
分支合并到master
分支的时候,会出现一个分叉合并。
通过rebase
合并
bash
# 切回到要合并的分支
git checkout dev
# 将合并记录变成一条线、将master分支代码放到dev分支
git rebase master
# 切换回master分支,将dev分支的代码merge过来
git checkout master
git merge dev
4.3 git rebase的第三种使用场景
其实和第二种一样,就是当我们在拉去远程仓库代码的时候可能会产生冲突,要想在合并冲突的时候不要那种分叉线,我们就使用rebase
git fetch origin dev + git rebase origin/dev
5. 多人协同
4.1 基础命令
bash
# 克隆仓库到本地
git clone 仓库地址
# 拉去仓库代码到本地
git pull
# 推送代码到远程仓库 -u 代表是默认的,下次直接推送到该地址的master分支上
git push -u origin master
4.2 更新远程代码冲突
比如说两个人同时改了同一块的代码,同学A由于单身多年,手速比较快,先将代码推送到了远程仓库。当同学B写完之后先将自己的代码commit
。然后去更新远端的代码,这个时候发现他们改了同一行,然后出现了冲突。
解决冲突就是找到对应的文件,然后手动解决冲突。
bash
git add .
git commit -m "解决冲突"
git push origin dev
4.3 git fetch 和 git pull
pull 相当于直接将远程仓库的代码拉取到了我们本地的工作区
fetch相当于把远程仓库的代码拉取到我们本地的版本库
git pull origin dev = git fetch origin dev + git merge origin/dev 因为我们fetch下来的远程代码,为了表示他是远程的分支,前面会加上一个origin代表远程