目录

Git-初识Git-Git基本操作

【Git】— 初识Git && Git基本操作

Welcome to 9ilk’s Code World

https://img-blog.csdnimg.cn/direct/a50a22d51dca4ff4beeb1e31a29177aa.jpeg

(๑•́ ₃ •̀๑) 个人主页:

(๑•́ ₃ •̀๑) 文章专栏:


本篇我们来初步认识Git企业级应用是什么,有什么用以及Git基本操作。


🏠 初始Git

提出问题

在日常生活中,我们进行软件开发或日常文档维护,可能遇到以下问题:我们对文档进行多次修改,形成多个版本v1 v2 v3 v4… 长此以往我们的文档副本越来越多,每个版本都有各自内容,但最终只有一份会被我们采用,但我们想从不同版本汲取优点,面对这么多版本,我们是不清楚之前的每个版本的修改内容的,这并不方便我们进行维护,影响我们的开发效率。有什么解决方案吗?

解决方案

面对上面的问题,我们急需一个 能记录每次修改以及版本迭代的管理系统 ,这就需要引出 版本控制器 的概念,我们的 Git 就是当前主流的版本控制器。版本控制器,通俗讲就是 能让你了解到一个文件的历史,以及它的发展过程的系统,即一个可以记录工程的每一次改动和版本迭代的管理系统,同时也方便多人协同作业。

我们的主角Git是当前最主流的版本控制器,它 可以控制电脑上所有格式的文件,例如doc execl dwg dgn等等。 对于我们开发人员来说,Git最重要的就是可以帮助 我们管理软件开发项目中的源代码文件

🏠 Git 安装

Centos:

git --version
sudo yum install git -y   

Ubuntu:

sudo apt-get remove git -y
git --version
sudo apt-get install git -y 

🏠 Git基本操作

本地仓库创建

如果想使用Git管理文件,我们必须把这些文件放在Git仓库中, 仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来

先创建一个目录做测试:

mkdir gitcode

创建Git本地仓库( 注意命令要在⽂件⽬录下执行 ):

git init

当创建成功我们可以看到以下提示:

https://i-blog.csdnimg.cn/direct/343afcb78b89430c96ab9f5fedcf4fa7.png

使用ls -a 命令我们发现,我们当前目录下多了个 .git 的隐藏目录,它是Git 用来跟踪管理仓库的不要手动修改这个目录里面的文件,不然乱改会把Git仓库给破坏了

https://i-blog.csdnimg.cn/direct/64ef6bf0ee5d4ad9b3218fcfd2a2cc3a.png

本地仓库配置

将本地仓库创建好之后,我们最好对两个配置项email name进行配置。

git config [--global] user.name "Your Name"
git config [--global] user.email "email@example.com"
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可
  • –global是一个可选项 ,如果使用该选项,表示这 台机器上所有的Git仓库都会使用这个配置 。如果你希望在不同仓库中使用不同的name或e-mail,可以不要–global选项,但 注意的是,执行命令时必须要在仓库里。

查看配置

git config -l 

https://i-blog.csdnimg.cn/direct/b66861e4252a447e89c37c75f5686e8c.png

重置某个配置

git config [--global] --unset user.name
  • 注意对于设置了–global选项的配置项,unset时需要带上–global

认识工作区,暂存区,版本库

zhuang@VM-8-14-ubuntu:~/gitcode$ touch  ReadMe
zhuang@VM-8-14-ubuntu:~/gitcode$ ls
ReadMe

思考以下问题:当我们在gitcode下创建文件时,这个文件就会受到版本管理了吗?如果放在.git目录下呢?

答案是无论放在它们两哪个都不会受到版本管理,而且我们之前也说过不允许在.git下手动修改,误操作可能会导致整个本地仓库出错。

面对这个问题我们需要了解三个区域:

  • 工作区 :是在电脑上你要写代码或文件的 目录 。对应我们的gitcode目录。

  • 暂存区 :英文叫 stage或index 。一般存放在 .git 目录下的 index文件(.git/index)中 ,我们

    把暂存区有时也叫作索引(index)。

  • 版本库 :又名仓库,英文名repository。工作区有一个隐藏目录录. **git,它不算工作区,而

    是Git的版本库** 。这个版本库里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git

    都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以"还原"。

工作区、暂存区、版本库三者的关系如下:

https://i-blog.csdnimg.cn/direct/d8c2ed8599e34e48b75cff7e174b70be.png

  • 图中左侧为工作区,右侧为版本库。Git的版本库里存了很多东西,其中最重要的是暂存区。
  • 在创建Git版本库事,Git会为我们自动创建一个 唯一的master分支 ,以及 指向master的一个指针叫HEAD。
  • 当执行 git add 操作时,会 将工作区修改的内容保存到版本库的暂存区 中,暂存区目录树的文件索引会被更新。注意: 这里工作区修改的内容不仅仅指的是新增和修改,还有删除!
  • 版本库中还有一个模块,叫 “对象库(objects)”, 里面存储一堆 git对象,维护git对象相当于维护了文件的所有版本,即进行了版本管理。
  • 当执行 git commit 操作时,会把 暂存区的index树写到master分支下master分支会做相应的更新注意:git对象都存在objects里,因此暂存区存的是一个个git对象的索引,它是轻量级的一个区域
  • master指向的是当前分支,即最新commit,即最近的一个版本。

总结 :通过新建或粘贴进目录的文件,并不能称之为向仓库中新增文件,而只是在 工作区新增文件 。必须通过两板斧 git addgit commit 才能将文件添加到仓库中进行管理。

小细节:当我们刚创建完一个新目录,还没有git add时,是查看不了暂存区的,即.git目录下的index目录。

https://i-blog.csdnimg.cn/direct/ea937dc5b2c8494cbab08f00e523bfc6.png

添加文件

(1)场景一:

先在gitcode目录下创建一个文件ReadMe,给ReadMe文件添加内容:

https://i-blog.csdnimg.cn/img_convert/d187aab71d4a1e27d253002ae2a81341.png

git add : 添加内容进暂存区

git add ReadMe

当然git add我们可以灵活使用:

git add [file1] [file2].. //添加一个或多个文件到暂存区
git add [dir] //添加指定目录到暂存区,包括子目录
git add . //添加当前目录下的所有文件

git commit命令将暂存区内容添加到本地仓库:

git commit -m "ReadMe" //提交暂存区全部内容
git commit [file1] [file2]... -m "message"//当然也可以提交暂存区的指定文件
  • git commit 后面的 -m 选项 ,要跟上描述本次提交的message,由用户自己完成,这部分内容绝对不能省略,并要好好描述,它们用来记录你的提交细节,方便我们开放以及他人协作。

我们一次性add和commit多个文件:

zhuang@VM-8-14-ubuntu:~/gitcode$ touch file1 file2 file3
zhuang@VM-8-14-ubuntu:~/gitcode$ git add file1
zhuang@VM-8-14-ubuntu:~/gitcode$ git add file2
zhuang@VM-8-14-ubuntu:~/gitcode$ git add file3
zhuang@VM-8-14-ubuntu:~/gitcode$ git commit -m "add 3 file"
[master e42d583] add 3 file
 3 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file1
 create mode 100644 file2
 create mode 100644 file3

完成之后,我们可以使用 git log命令显示从最近到最远的提交日志,并且可以看到我们commit时的日志消息

https://i-blog.csdnimg.cn/direct/fd8fdd3552464863b1adc40946daafa7.png

  • commit后跟着的一串字符串是我们每次提交的 commit id(版本号),Git的commit Id是一个SHA1计算出来的一个非常大的数字,用十六进制表示。

如果嫌git log一次性输出信息太多,可以加上–pretty=oneline:

https://i-blog.csdnimg.cn/direct/aa74734ad7224b19a7ae400b3aded7d4.png

经过上面两次提交,我们查看.git目录下发生什么变化:

https://i-blog.csdnimg.cn/direct/e9fc4b2005b24a0595782a6655c6f0e9.png

  • 我们发现新增了 暂存区index ,add后的内容就是添加到这里的。

https://i-blog.csdnimg.cn/direct/7853d86c1b79491d8c43b99d2305e41f.png

  • HEAD指针指向的就是默认master分支

https://i-blog.csdnimg.cn/direct/771e5e46c2414607a92c6d9d14f63a0f.png

  • 我们查看master,里面保存的其实就是当前最新的一个commit ID,即一个git对象。

objects 为Git的对象库,里面包含了创建的各种版本库对象以及内容,当执行 git add命令时,暂存区的目录树被更新,同时工作区修改的文件内容被写入到对象库中的一个新对象中 ,就位于".git/objects"目录下,我们可以观察下:

https://i-blog.csdnimg.cn/direct/7eb6cc6ce05f48c7b682abf6a7b66eb8.png

  • 查找objects时,要将commit id分成两部分,其中前两位是文件夹名称,后38位是文件名称

https://i-blog.csdnimg.cn/direct/6216c33fb28148cd8593d8f95d7a0f5b.png

  • 找到这个文件之后,一般不能直接看到里面是什么,该文件是经过 SHA(安全哈希算法) 加密过的文件,我们可以使用 git cat-file -p + commit id 来查看

https://i-blog.csdnimg.cn/direct/5c28bc91381b417991f7b40a8b7c355d.png

  • 其中还有一行 tree, 我们可以使用同样方法查看

https://i-blog.csdnimg.cn/direct/2ee107b15f4b40ec86932e5ac391b98a.png

  • 在查看ReadMe对应的commit ID,我们发现 我们第二次提交时对其修改的内容被git记录下来

总结:在本地的git仓库中,有几个文件或目录很特殊

  1. index : 暂存区,git add后会更新该内容

  2. HEAD:默认指向master分支的一个指针。

  3. refs/heads/master:文件保存当前master分支的最新commit id

  4. objects: 包含了创建的各种版本库对象及内容,可以简单理解为 存放了git维护的所有修改。

(2)场景2

https://i-blog.csdnimg.cn/direct/4b835b0b7a804a6e9d388ad98ceeb948.png

这里我们先创建file4,再创建file5,将file4进行add存放到暂存区,这里显示只有一个文件改变了,不应是新增了两个文件吗?

我们应该弄清楚,git add只是将文件添加到暂存区,git commit是将暂存区内容添加到本地仓库中。我们并没有git add file5导致其没有在暂存区中维护,因此我们commit时只将已经在暂存区中的file4提交了,要想提交file5,只需对其再进行两板斧add commit即可。

https://i-blog.csdnimg.cn/direct/36db2ad3278e48e986b304fd87781c1a.png

修改文件

Git比其他版本控制系统设计得优秀,因为 Git跟踪并管理的是修改,而非文件。

我们之前说过,修改不仅仅是修改内容,新增一行,删除一行也是修改,甚至在工作区新增文件也是一个修改。

我们在工作区对ReadMe文件内容进行修改:

https://i-blog.csdnimg.cn/direct/9ac3510bf0eb41eba487831f503b98ea.png

此时仓库中的ReadMe和工作区中的ReadMe是不同的,我们可以使用 git status 查看在你上次提交之后是否对文件有再次修改

https://i-blog.csdnimg.cn/direct/58c0767e66974289b6b5f016b7e9dae6.png

git status只能查看哪个文件变化/修改,但不知道具体修改内容(对于大文件我们cat无法准确得知修改内容)

我们可以使用git diff [file] 命令显示暂存区和工作区文件的差异,显示的格式正式Unix通用的diff格式

zhuang@VM-8-14-ubuntu:~/gitcode$ git diff ReadMe
diff --git a/ReadMe b/ReadMe //a是改动前 b是改动后
index 8d0e412..05fe86c 100644
--- a/ReadMe //改动前
+++ b/ReadMe //改动后
@@ -1 +1,2 @@   //-1代表改动前第一行内容 原文件在第1行开始,并且原文件只有1行内容。
 hello git      //+1,2表示改动后从第一行开始,连续两行的内容  新文件从第1行开始,并且新增了1行,使得现在有2行内容。
+hello world 

也可以使用git diff HEAD – [file]来查看版本库和工作区文件的区别

https://i-blog.csdnimg.cn/direct/d75ab5a7246a470cb574cc3c42445c66.png

此时我们把修改的ReadMe再git add会提示在暂存区修改了:

https://i-blog.csdnimg.cn/direct/c13ae5e5ba2d489caa36b03757312ff5.png

此时再commit即可:

https://i-blog.csdnimg.cn/direct/6e604df43e9244e098e25d84f8805224.png

版本回退

我们知道Git能够管理文件的历史版本,这也是版本控制器重要的能力,如果有一天你发现之前工作的内容出现很大问题, 需要在某个特定的历史版本重新开始,此时就需要版本回退。

Git中用于版本回退的命令是 git reset可以指定退回某一次提交的版本

我们之前的操作使得ReadMe存在两个版本,第一个版本只有一行内容Hello git,第二个版本新增了一行内容Hello world,git reset本质 是将版本库 中的内容进行 回退 ,而 工作区和暂存区是否回退 取决于它的 三个选项:【–soft】【–mixed】【–hard】

  • –soft : 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。

https://i-blog.csdnimg.cn/direct/8d6f67eabb5342f7846d102bb321cc3b.png

  • –mixed选项: 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区 的内容退回为指定提交版本内容,工作区文件保持不变

https://i-blog.csdnimg.cn/direct/3e3db27be3b64877ae6e167e40c17f22.png

  • –hard: 参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为工作区会回滚 ,你没有提交的代码就再也找不回了,所以

    使⽤该参数前⼀定要慎重

https://i-blog.csdnimg.cn/direct/3922b003283a4bcba0587c4e8df41a2c.png

我们使用–hard选项演示一下:

https://i-blog.csdnimg.cn/direct/875b718ab1904e759f7780b604df2bdc.png

我们发现我们的三个区域都回退了,如果我们想反悔,可以使用之前打印的commit ID复原出file1 file2 file3。 但这样做的前提是commit ID没有被清除

https://i-blog.csdnimg.cn/direct/729b1462a36b4a6baae596deea35c459.png

如果commit id被清除了呢?此时我们还可以使用命令 git reflog查看本地记录的每一次提交id进行reset

https://i-blog.csdnimg.cn/direct/a245520041ed49d493b4c85fc1e78dc7.png

注:这个55604d7其实是commit ID的一部分,也可以用来进行回退

https://i-blog.csdnimg.cn/direct/3af2d6f1f55741a3a6f252d25c41fda4.png

思考一个问题 : Git版本回退的速度是比较快的,为什么呢?

https://i-blog.csdnimg.cn/direct/d8b8f09f18c243ee95d6a50643fb6663.png

Git在内部有个指向当前分⽀(此处是master)的HEAD指针, refs/heads/master⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git仅仅是给refs/heads/master中存储⼀个特定的version

撤销修改

(1)情况一:对于工作区的代码还没add

在原来基础上我们给ReadMe新增上一行内容:

https://i-blog.csdnimg.cn/direct/345771403d4745b7a7a7cb6d005ff0a3.png

此时我们如果想撤销工作区的内容,可以使用 git checkout – 撤销的文件名:它其实就是帮我们将工作区文件回到最近一次add/commit的状态(注意加上两杠)

https://i-blog.csdnimg.cn/direct/49c1bf6456d2471bb64ada4f63eb6896.png

当工作区的代码没有add时,我们可以使用两种方式进行撤销:

1. 手动使用Vim工具撤销 — 对于这种方式我们不推荐,如果代码写了几天但一直没有add,此时修改容易出错

2. 我们推荐使用git checkout – [filename]

(2)情况二:已经add,但是没有commit

我们先对ReadMe文件修改,新增一行内容,add之后使用git status查看状态:

https://i-blog.csdnimg.cn/direct/4757a11206084d169b3be95b6750a8df.png

此时我们可以使用的 git reset作用更详细来说是回退到版本库的当前版本,我们可以使用–mixed选项先将暂存区回退到版本库的当前版本,再使用git checkout对工作区进行撤销:

https://i-blog.csdnimg.cn/direct/5d077e10dfbe447198bd2b83c8b2f167.png

补充:

git reset --mixed HEAD ReadMe //回退到当前版本
git reset --mixed HEAD^ //回退到上个版本 ^^是回退到上上个版本

(3)情况3:已经add,也已经commit

此时版本库是最新版本,此时可以使用 git rest的–hard选项将三个区域都回退 ,但是 前提commit之后,没有push,撤销才有效。(实际公司开放跑的代码都是围绕远程仓库的,所以撤销主要目的是不影响远程仓库),Push操作是将版本从版本库->远程仓库。

演示:

准备工作

https://i-blog.csdnimg.cn/direct/aa0d636bec504ca1ab4416ca4d93beb4.png

撤销

https://i-blog.csdnimg.cn/direct/fe7af08c6ea3437ea00f3736805adea4.png

删除文件

rm是删除工作区的文件 ,但对于 本地仓库并没有删掉, 实际应该怎么删除呢?

https://i-blog.csdnimg.cn/direct/509521a31f024c7e8970d0f45c641e06.png

此时就完成一个文件在工作区 暂存区 版本库的修改,我们总结一下删除文件的步骤:

1. rm — 删除工作区内容

2. git add — 提交工作区的变动

3. git commit — 更新到版本库

git rm + 要删除文件 : 该命令帮我们删除工作区文件同时帮我们add,我们只需要commit即可

https://i-blog.csdnimg.cn/direct/241f6df216114d8897472663b92696bc.png


总结一下:

  1. Git是一个版本控制器,跟踪的是版本的修改。

  2. git init 创建本地仓库

  3. git三板斧 : git add -> 工作目录放到暂存区 git commit 暂存区->版本库master git push 本地仓库->远程仓库

  4. 版本回退:git reset,存在三个选项–soft –mixed –hard

  5. 查看相关命令:git log 查看commit id , git status 查看仓库状态