目录
写在前面的话
为什么要有Git(git初识)?
Git安装(Centos为例)
Git基本操作
创建Git本地仓库
Git配置
认识工作区、暂存区、版本库
概念认识
添加文件
查看.git文件
修改文件
版本回退
撤销修改
情况一:对于工作区的代码,还没有 add
情况二:已经 add ,但没有 commit
情况三:已经 add ,并且也 commit 了
删除文件
写在前面的话
没实习前接触过git,但是一直没在意,心里想git不就是远端存储代码吗,我到时候直接在平台上把文件手动上传上去也可以啊,何必大费周章学这么多git知识,那么麻烦。
自从前两个月实习后,才意识到git在企业中是多么的重要,几乎所有的工作都在git的基础上进行的,也意识到git是多么的强大。包括后面才知道的版本控制,分支管理,多人协作等等。比如其他同事代码有问题,我可以直接一条命令切换到这个同事的分支上,便可以看到该同事所写的代码;以及完成某个任务时,内容需要不断的修改,每个版本间的改动等等,都可以直接切换且管理起来,特别厉害。
所以同学们还是尽量早点学会git好,当初进去的时候对git一点都不理解,也耗费了挺长时间进行学习,走了挺多弯路,经过不断的学习,对git略有了解了,所以在此系统记录一下git的使用和原理.
为什么要有Git(git初识)?
在我们大学学习的时候,,有没有遇到这样的情况:我们在编写各种⽂档时,为了防⽌⽂档丢失,更改失误,失误后能恢复到原来的版本,为此不得不复制出⼀个副本,然后在这个副本的基础上进行改动,避免 改了半天改错了,原来的版本也恢复不回去了。
“报告-v1”
“报告-v2”
“报告-v3”
“报告-确定版”
“报告-最终版”
每个版本有各⾃的内容,但最终会只有⼀份报告需要被我们使⽤。
但在此之前的⼯作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的⽂件就越来越多,⽂件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各⾃都是修改了什么
吗
⽂档如此,我们写的项⽬代码,也是存在这个问题的!
那如何解决呢?
这就用到了版本控制器:为了能够更⽅便我们管理这些不同版本的⽂件,便有了版本控制器。所谓的版本控制器,就是能让你 了解到⼀个⽂件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录⼯程的每⼀次改动和版本迭代的⼀个管理系统,同时也⽅便多⼈协同作业。
⽬前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的⽂件,例如doc、excel、dwg、dgn、rvt等等。
Git安装(Centos为例)
这里git的安装操作只简单介绍一下Linux下centos的安装过程,安装不是我要说的重点。像在Windows,MAC或Ubuntu等系统下的安装,可以去b站或网上搜索相关教程.
1. 首先在命令行输入git,来看有没有安装git,若没有,系统则会弹出如下警告:
$ git
-bash: git: command not found
若你已经安装,则会弹出git的相关使用方法.
2.安装git
sudo yum -y install git
3.查看git 版本
git --version
若是有对应的版本,则说明已经安装成功:
Git基本操作
创建Git本地仓库
首先提前说一下,我们既然要对某个文件进行版本控制,那么该文件位置一定是特定的。如果该文件位置是随意的,那么git该如何跟踪 它的修改呢?显然是不可能的.
所以需要跟踪修改的文件 一定要位于Git仓库中,这样git才能跟踪修改。
那么如何初始化呢?
首先,仓库是进⾏版本控制的⼀个文件目录,所以我们要先创建一个目录,我命名为gitnode,然后进入该目录,使用以下命令初始化仓库:
git init
此时我们的目录下面会多出来一个隐藏文件:.git文件,是用来进行版本控制和跟踪改动的。千万不要随意修改.git文件下的任何内容:
这样一个git仓库便创建好了.(注意:git仓库(又叫版本库)是指.git这个目录,而不是创建的gitnode这个目录!后面会细说)
Git配置
当安装Git后⾸先要做的事情是设置你的 用户名称和e-mail地址 ,这是⾮常重要的。配置命令为:
git config [--global] user.name "Your Name"
git config [--global] user.email "email@example.com"
其中:
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可
# [--global]可以先不加,等下说明作用。
配置完成后,可以使用以下命令查看自己的配置:
git config -l
注意到刚才的命令有个 --global 选项,这个选项的作用是什么呢?
首先我们要知道,我们不仅仅只有一个git仓库,而是可以有多个git仓库,加上--global(注意不要加[])可以让改配置在所有的git仓库中生效,而不只是当前git仓库.
如果我们想删除配置项,可以使用如下指令:
1.删除某个仓库中的配置:
git config --unset user.name
git config --unset user.email
2.删除所有仓库中的配置
git config --global --unset user.name
git config --global --unset user.email
认识工作区、暂存区、版本库
概念认识
当我们在gitnode目录下创建一个文件ReadMe,这个文件是否被git管理了呢?
答案是否定的.我们真正的git仓库是在.git文件中的,我们需要将文件添加到.git文件中才能被进行管理。
此时当前这个gitnode目录叫做工作区,即在电脑上要写代码或文件的目录。
而.git文件被称为版本库,也就是我们一开始说的仓库。但它不属于工作区,⽽是Git的版本库。
这个版本库里面的所有文件都可以被Git管理起来,每个文件的修改、删除 ,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
我们具体来看一下他们的关系:
版本库中有stage暂存区和右边的master分支等,至于这个master分支,我们先不用管,后面我会详细介绍。
也就是我们在工作区中的修改(包括新增的文件,对文件内容的修改,删除的文件)等,都要先add到 版本库中的stage(又叫暂存区或索引)中,然后再commit到分支上。这样文件才真正意义上被git管理起来了,这是目前的流程.
这里再补充一点:git之所以轻量化,是因为在版本库中,有一个名为objects的对象库,所有修改的工作区内容都会写入objects对象库中的一个新git对象中,而每个文件正存放的是这些一个个git对象,相当于只是存放了改动,没有存放全部代码。
添加文件
我们刚才说了基本的概念和流程,但具体每一步如何做,我们还没有说,接下来我们将讲解它.
首先我们在工作区中的ReadMe文件添加一行hello,world,然后我们使用git add指令将其添加到暂存区中:
有以下三种方式:
- 添加⼀个或多个文件到暂存区:
git add [file1] [file2] ...
- 添加指定目录到暂存区,包括子目录:
git add [dir]
- 添加当前目录下的所有⽂件改动到暂存区:
git add .
当然git add + 指定路径下文件都可以.
将其添加到暂存区中之后,我们需要使用git commit 指令将暂存区内容添加到指定仓库中:
- 提交暂存区全部内容到本地仓库中:
git commit -m "message"
- 提交暂存区的指定⽂件到仓库区:
git commit [file1] [file2] ... -m "message"
其中message一定要写,写上你本次对该文件的改动,这是给我们其他同事看的,方便知道你此次对该文件做了哪些改动与处理.
可以看到已经被管理起来了,一个文件被改动(新建的文件ReadMe),1次插入(新增了一行"hello world").
假设此时我们又新增了一个文件file,并且不做任何修改:
可以发现一个文件被改动,然后没有任何的插入和删除。
这里再告诉大家一个命令,叫做
git log
该指令可以查看所有的git 提交记录,如下:
我之前两次的提交记录都显示了出来,这便是git log的作用
查看.git文件
在进行了这两次提交操作后,.git文件中有哪些变化呢?
这是我一开始没有进行任何提交时的.git目录:
这是当我提交完两次之后的.git目录图:
我们首先可以看一下HEAD文件中有什么:
它指向了.git目录下的refs/heads/master文件,那我们查看一下该文件里面有什么:
是这一串commit id,反过来我们再来看一下我们的提交时的commit id:
可以发现正好是我们最新一次的提交的commit id,也就是说HEAD指针指向了我们最新一次的提交,当然objects中使我们每一次的改动,我这里也不查看了。
总结⼀下,在本地的git仓库中,有⼏个⽂件或者⽬录很特殊
- index:暂存区, git add 后会更新该内容。
- HEAD:默认指向master分⽀的⼀个指针。
- refs/heads/master:⽂件⾥保存当前 master 分⽀的最新 commit id 。
- objects:包含了创建的各种版本库对象及内容,可以简单理解为放了git维护的所有修改。
修改文件
Git⽐其他版本控制系统设计得优秀,因为Git 跟踪并管理的是修改,而非文件。
什么是修改?⽐如你新增了⼀⾏,这就是⼀个修改;删除了⼀⾏,也是⼀个修改;更改了某些字符,也是⼀个修改;删了⼀些⼜加了⼀些,也是⼀个修改;甚⾄创建⼀个新⽂件,也算⼀个修改。
我们在ReadMe文件中,添加如下几行:
保存退出后,我们使用
git status
来查看当前文件的状态:
可以发现,它告诉我改动还没有暂存起来提交,也就是还没有添加到暂存区,第二个红框告诉我们修改的文件是ReadMe.
但是它只告诉了我们哪个文件被修改了,没告诉我具体有哪些改动,我们该如何查看呢?
可以使用
git diff [file]
来查看暂存区和工作区文件的差异,显⽰的格式正是Unix通⽤的diff格式.
如下:
我来解释一下@@ -1 +1 4 @@什么意思
-1表示改动前的第一行 是hello,world
+1 4 表示改动后的从第一行开始的后4行(如图所示的那四行).后面的3行前面的+代表是新插入的.
回到刚才所说的,git status,此时当我们add到暂存区后,再次查看状态:
此时告诉我们将要被提交,意思是添加到工作区中了,需要commit.
当我们commit后:
它此时告诉我们没有可以提交的了。工作目录是空的,至此我们也算提交完成了.
版本回退
之前我们也提到过,Git能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现当前的⼯作做的出现了很⼤的问题,需要从某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
执⾏ git reset 命令⽤于回退版本,可以指定退回某⼀次提交的版本。要解释⼀下“回退”本质是
要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定:
git reset [--soft | --mixed | --hard] [HEAD]
- --soft 参数对于⼯作区和暂存区的内容都不变,只将版本库回退到某个指定版本。
- --mixed 为默认选项,使⽤时可以不⽤带该参数。该参数对于⼯作区⽂件保持不变,将暂存区和版本库内容退回为指定提交版本内容,
- --hard 参数将暂存区、⼯作区和版本库都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
可以看这个表格进行区分:
我们先添加了git,后添加的world,使用三个选项后会导致的结果都显示了出来.
HEAD参数可以如下使用:
HEAD 说明:
◦ 可直接写成commit id,表⽰指定退回的版本
◦ HEAD 表⽰当前版本
◦ HEAD^ 上⼀个版本
◦ HEAD^^ 上上⼀个版本
◦ 以此类推...
• 可以使用~数字表示
◦ HEAD~0 表⽰当前版本
◦ HEAD~1 上⼀个版本
◦ HEAD^2 上上⼀个版本
◦ 以此类推...
那我们来使用一下git reset.
先来看一下我这三次版本的改动.
我现在如果想回退到第二个版本,那么ReadMe文件中新插入的三行内容应该会消失:
我们使用git reset --hard 第二个版本的commit id 进行回退
可以发现第三个版本的内容确实没了,但是我如果后悔了,想重新回到第三个版本该怎么办呢?
git log查看下所有commit id? 我们试试:
可以发现我们只有两次提交的commit id,第三次的已经没有了,那么该如何恢复呢?
这里我们用到了如下命令:
git reflog
我们可以通过使用git reflog
命令,就可查看到所有历史版本信息。由于查看所有历史版本信息的目的,大多是为了进行版本回退或恢复操作所使用,从中找到所需的commit索引,所以该命令被命名为reflog
,即:引用日志。
这样我们便可以 再次通过git reset来恢复了:
此时我们发现,我们又回到了第三个版本,ReadMe中的内容也全部恢复了.
git log 和 git reflog的关系如下:
图片来源于简书:繁华似锦Fighting
撤销修改
如果我们在我们的⼯作区写了很长时间代码,越写越写不下去,觉得自己写的实在是垃圾,想恢复到上⼀个版本,该如何做呢?
情况一:对于工作区的代码,还没有 add
两种方式:
1.自己手动删除写的代码(但是如果写了很长时间,哪些代码是新增的,哪些删除了,我们不会记得非常清晰,很容易出错,因此不建议)
2.使用 git checkout -- [file]命令撤销当前工作区更改
可以发现使用该指令后,原来工作区中的代码改动被撤销了.
情况二:已经 add ,但没有 commit
此时我们需要将暂存区中的内容和工作区中的内容全部撤销回到上一个版本.该如何做呢?
我们来回忆⼀下刚讲过的 git reset 回退命令,该命令如果使⽤ --mixed 参数,可以将暂存区
的内容退回为指定的版本内容,但⼯作区⽂件保持不变。那我们就可以回退下暂存区的内容了!
这样暂存区中的代码就已经被撤销了,但是还有工作区中的代码没有被撤销,那我们可以按照刚才的方法,使用 git checkout -- [file]命令撤销当前工作区更改。
两个方法组合起来便将暂存区和工作区中的修改全部撤销了.
综上,使用这两句命令便可完成操作:
git reset --mixed HEAD
git checkout -- [file]
或者直接干脆点,将选项改为hard,将工作区、暂存区、版本库全部回退到当前版本,因为此时还没有commit ,所以版本库还是原来的不变,工作区和暂存区全部回退到了和当前版本库一样的代码.
情况三:已经 add ,并且也 commit 了
这个情况适用于comomit但还没有push到远端仓库时的代码,至于远端仓库,后面会说。
同样地我们只需要git reset --hard HEAD^ 即回退到上一个版本,所有的内容工作区和暂存区及版本库也全部回到上一个版本了.
这便是所有情况的一个总结了,xxx code为新增的代码以及所处的位置:
删除文件
当我们想删除一个文件时,我们可以有两种方法可以删除:
1.按正常的流程,删除文件后,add到暂存区,然后commit
2.使用git提供的指令来删除,然后commit提交
第一种方法我就不演示了,直接说第二种方法:
git提供的删除指令是
git rm
例如我们想删除file文件,git rm会讲文件从工作区和暂存区中删除(第一种普通的rm删除只会删除工作区的文件,因此需要add和commit),但版本库中还没有删除,因此还需要commit一次,如下:
至此,关于git的基本操作就完成了 ,感谢您的阅读,若是有不理解或疑问的地方,欢迎评论区留言哦~
,