手把手教你安装Git,萌新迈向专业的必备一步
GIT命令只会抄却不理解?看完原理才能事半功倍!
常用GIT命令详解,手把手让你登堂入室
GIT实战篇,教你如何使用GIT可视化工具
经过前三期的学习,相信大家对GIT的已经基本熟悉了。出于防患于未然,笔者还是决定讲一下日常操作中一些必须关注的点,即本地代码的丢失问题,GIT中有很多命令会更改工作区内容,我们今天就来详细地解析一下这些操作,做到防患于未然
作者简介:战斧,从事金融IT行业,有着多年一线开发、架构经验;爱好广泛,乐于分享,致力于创作更多高质量内容
本文收录于 GIT 专栏,有需要者,可直接订阅专栏实时获取更新
高质量专栏 云原生、RabbitMQ、Spring全家桶 等仍在更新,欢迎指导
Zookeeper Redis kafka docker netty等诸多框架,以及架构与分布式专题即将上线,敬请期待
一旦我们把某个目录下的文件托付给GIT,那么在很多场景下,一些GIT的操作将直接改变这个目录的文件,这也就是所谓的工作区
,要理清这个问题,我们必须先搞清楚工作区到底会和那些区域发生关联,我画了一个模型图供大家参考
可以看到,工作区与不少其他区域都有着交互,而这些交互都会改变工作区的内容。当然,在进一步详细讲解前,我们先简单介绍一下这些区域的概念,图中大部分的区域是我们在前面都提到过,至少相信大家对远程分支
、本地分支
和暂存区
应该是有一定了解的,不了解的同学请看《GIT命令只会抄却不理解?看完原理才能事半功倍!》 中的描述。这里着重讲解一下远程跟踪分支 和 贮藏区
远程分支
与本地分支
通常是一对一的关系,但是它们并不是直接沟通的,它们有一个“中介”叫做远程跟踪分支
,比方说我们使用
git branch -a
得到了这样的结果
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/master_copy
其中以 remotes 开头的就是远程跟踪分支,它们可以说是远程分支的在本地的镜像,当然啦,这些跟踪分支不会自动更新或创建,比如此刻我在远程建了一个新分支叫 master_copy2,本地并不会察觉到的,也不会自己建一个远程跟踪分支
贮藏区其实是GIT中一个比较特殊的区域(它的底层实际上类似于分支),当然由于翻译与功能的问题,有的人会把贮藏区
(stash)和暂存区
(index)混淆,但其实两者功能并不一致。
如果说工作区是加工台,那么当我们需要从一个工作切换到另一个工作时,如果本次工作已完成,我们就需要把本次加工完的零件放入暂存区
(index),然后再从暂存区提交到本地分支;但是,如果本次的工作没有完成,我们是被迫要进行下一项工作时,我们就可以把本次还未完工的半成品放入贮藏区
(stash),等我们什么时候又需要回来继续这项工作时,又可以去贮藏区
(stash)把这个半成品拿回来继续加工
在一众操作中,分支的切换是最常见的操作,它的模型如下
只要你记住一点,工作区的代码是始终跟随 HEAD
的变化而变化的,我们切换分支实际上就是在切换 HEAD
的位置,比如当前我们是指向master分支,如果我们想切换到iss94-1分支,那么就会变成这样
分支的合并其实前面已经做过比较详细的解释了,这里我们还是一样的以图来说话,当前分支是iss95,那么我的的工作区取的也是iss95最后一次提交的代码,即HEAD的位置。
如果在此时,我们执行
git merge master
此刻iss95就有了一次新提交,这次提交叫合并提交,我们的工作区代码将会被更新,此时的工作区将拥有原master和原iss95的所有代码。当然,必须再次重申,合并其实影响的只有本分支,即iss95,而master其实并没有被改变,此刻如果你切换分支去master,那它还是原master的代码
我们这里的拉取指的是pull,相信这个命令也有很多小伙伴用,比如我们很久没更新分支了,此时我们的图示如下,可以看到远程分支多了好几次提交,而我们本地则自己提交了一次
如果我们此时执行pull
进行拉取,其实执行的是fetch 和 merge 两步操作,第一步fetch
是把远程分支的代码拉下来,远程跟踪分支得到更新。然后执行merge
,把远程跟踪分支和本地分支进行合并,最终得到如下的结构
这种操作会导致本地工作区被更新,其本质还是merge操作导致分支多了一次提交,进而影响到本地工作区
如果说前面的操作带给工作区的改动是不可预知的,因为你无法预知其他分支的代码,因此自然不知道操做后本地会有哪些代码被改变。但贮藏不一样,因为贮藏的这些代码的变动是你自己改动的,所以其“危险性”就显得小了许多。相反,如果你预感某些操作可能会导致本地代码遗失,不妨先主动将代码贮藏起来,才做后再从贮藏去取回。
Git stash
命令实际上会将当前工作区中未提交内容的修改暂存起来,并将工作区恢复到最后一次提交的状态。这个操作是通过保存当前工作区的修改,包括新增的、修改的和未跟踪的文件,然后再将工作区恢复到最后一次提交的状态来实现的
我们如果是使用Idea的同学,很容易用到的一个功能就是rollback,通常是我们做了一些代码的修改,但感觉不对,又不想一行行删代码,于是想直接进行代码的回退。
Git中的rollback主要是指将代码恢复到之前的版本。但是,GIT中其实并不存在rollback命令,其主要依赖于 git checkout
和 git reset
命令进行回滚:
git checkout
命令可以将工作区中的某个文件恢复到指定版本的状态,但是该命令会丢失当前的修改,因此需要慎重使用。例如,将 file.txt 回退到最新提交的版本:
git checkout file.txt
git reset
命令可以将工作区和暂存区回退到指定版本,其作用是将 HEAD 指针指向指定的提交,同时重置暂存区和工作区的状态。例如,将工作区和暂存区回退到最新提交的版本:
git reset HEAD~
git checkout .
其中 HEAD~ 表示回退到上一个提交,. 表示恢复所有文件的状态。当然,reset 也有 soft
mixed
和 hard
的三种模式
git reset --soft <commit>
解释:这条命令会将 HEAD 指针指向指定的提交 ,但是不会修改暂存区和工作区的状态。这相当于撤销了该提交之后的所有修改,并且可以将这些修改再次提交。使用此命令可以修改之前的提交历史。
适用场景:在提交代码时,不小心将多次修改合并到了一起,想要将其中的一部分修改重新分开成多个提交记录,就可以使用 --soft 模式。
git reset --mixed <commit>
解释:这条命令会将 HEAD 指针指向指定的提交 ,将暂存区的内容清除,但是不会修改工作区的状态。也就是说,通过该模式可以撤销之前的 git add 命令把文件添加到暂存区的操作。同时,工作区的代码不会受到影响
适用场景:将不想提交的文件或修改从暂存区中移除,或者在进行多次提交之前,重新整理暂存区的内容。
git reset --hard <commit>
解释:这条命令会将 HEAD 指针指向指定的提交 ,并将暂存区和工作区的状态都重置为该提交的状态。这相当于彻底撤销了该提交之后的所有修改,同时删除了这些修改。
使用场景:在回退版本时,当需要彻底舍弃当前工作区的所有修改,并还原到回退版本的状态时可以使用 --hard 模式。