Git初识&&基本操作
- 1.初识Git
- 2.Git安装
- 3.Git基本操作
- 3.1创建Git本地仓库
- 3.2配置Git
- 3.3认识工作区、暂存区、版本库
- 3.4添加文件
- 3.5修改文件
- 3.6版本回退
- 3.7撤销修改
- 3.8删除文件
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.初识Git
不知道你工作或学习时,有没有遇到这样的情况:我们在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如:
“设计文档v1”
“设计文档v2”
“设计文档v3”
…
“设计文档v10”
随着版本的不断增多,维护好版本是很有挑战的。比如各自的版本修改的内容是什么我们还知道吗?
文档如此,我们写的项目代码,也是存在这个问题的!!
如何解决上述问题呢?
为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,通俗的讲就是一个记录每次修改和版本迭代的一个管理系统,同时也方便多人协同作业。
目前最主流的版本控制器就是 Git 。Git 可以控制电脑上所有格式的文件,例如 doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git 最重要的就是可以帮助我们管理软件开发项目中的源代码文件!
注意事项:
还需要再明确一点,所有的版本控制系统,Git 也不例外,其实只能跟踪文本文件的改动,比如 TXT 文件,网页,所有的程序代码等等。版本控制系统可以告诉你每次的改动,比如在第5行加了⼀个单词“Linux”,在第8行删了⼀个单词 “Windows”。
而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
2.Git安装
Git 是开放源代码的代码托管⼯具,最早是在Linux下开发的。开始也只能应用于Linux平台,后面慢慢的被移植到windows下,现在,Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。
Linux-centos下安装
首先,你可以试着输入Git,看看系统有没有安装Git
git
如果没有安装就执行下面的命令安装Git
sudo yum -y install git
查看 Git 安装的版本
git version
卸载Git
sudo yum -y remove git
Linux-ubuntu
如果你的的平台是ubuntu,安装git也相当简单
sudo apt-get install git -y
3.Git基本操作
3.1创建Git本地仓库
我们要想管理的文件和文档是可以存访在电脑上任意位置或者存访在服务器上任意位置,如果存在任意位置Git是不能进行追踪管理的,我们必须要把要管理的文件放在Git仓库中。只有在仓库下的文件才能把Git追踪管理。
在当前文件目录下创建⼀个 Git 本地仓库
git init
我们发现,当前目录下多了⼀个 .git 的隐藏⽂件, .git 目录是 Git 来跟踪管理仓库的,不要手动修改这个目录里面的文件,不然改乱了,就把 Git 仓库给破坏了。
其中包含 Git 仓库的诸多细节,后面我们在了解。
3.2配置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 仓库都会使用这个配置。如果你希望在不同仓库中使用不同的 name 或 e-mail ,可以不要 --global 选项,但要注意的是,执行命令时必须要在仓库里。
查看配置命令为:
git config -l
删除对应的配置命令为:
git config [--global] --unset user.name
git config [--global] --unset user.email
3.3认识工作区、暂存区、版本库
我们建立一个文件让Git管理它。
现在就有一个问题,目前Git可不可以管理ReadMe文件呢?
答案是不行的。这里可能就有疑问了,ReadMe不是已经放在本地仓库中了吗,之前说放入本地仓库的文件都可以被Git管理,为什么这里的ReadMe不能被管理呢?
其实ReadMe放在gitcode目录它其实不是本地仓库,真正的本地仓库是.git文件,仓库又可以称之为版本库 。注意不能在.git下进行任何手动修改,如果一旦进行任何修改可能会导致整个仓库都用不了。而gitcode这个目录称之为工作区。 工作区就是我们在电脑上或者服务器上写代码写文件的目录都可以称之为工作区。
- 工作区:是在电脑上你要写代码或文件的目录。
- 版本库:又名仓库,英文名 repository 。工作区有⼀个隐藏目录 .git ,它不算工作区,而是 Git 的版本库。这个版本库里面的所有文件都可以被 Git 管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
那如何将工作区的内容添加或者提交到版本库中以便管理起来呢?
其实最主要做两个操作,下面的图清晰展示了这一过程
图中左侧为工作区,右侧为版本库。Git 的版本库里存了很多东西,其中最重要的就是暂存区(索引)。
在创建 Git 版本库时,Git 会为我们自动创建一个唯一的 master 分支,以及指向 master 的一个指针叫 HEAD。(分支和HEAD的概念后面再说)
如何将工作区的文件使用git进行管理
首先第一步要做的是 add 操作,它会将工作区所有修改(新增文件、修改、删除)的内容保存到版本库的暂存区中。然后第二步要做的就是 commit 操作,它会将暂存区的内容提交到master分支下。做了commit操作之后我们才能真正意义上称之为将要管理的内容放到版本库中,让Git管理工作区的文件。
整个流程是这个样子,那具体add做了什么事情,commit做了什么事情呢?
其实在版本库中还有一个部分被版本库维护着,这个部分其实就是 对象库,这个对象库里面存储了一堆的git对象,而git对象又存储的是什么呢?
当我们在add操作的时候,新增工作区修改的时候会将修改的内容写入到git对象中,这个git对象就会被维护到git的对象库里。
对象库中会存一个个的git对象,每一个对象存每一次add修改的内容,所以是不是可以表示它维护了文件的所有版本啦,做到了对版本的管理。
暂存区里面是一个树状结构,它里面其实存的不是一个个对象,而是一个个修改的git对象的索引。
commit是将暂存区的这颗树写到master分支下,master分支也是一个树状结构,也存的是目录树,这个目录树下存的也不是一个个对象,存的和暂存区是一样的,存的是一个个修改的git对象的索引。
总结一下:
-
当对工作区修改(或新增)的文件执行 git add 命令时,暂存区目录树的文件索引会被更新。
-
当执行提交操作 git commit 时,master 分支会做相应的更新,可以简单理解为暂存区的目录树才会被真正写到版本库中
-
objects 为 Git 的对象库,里面包含了创建的各种版本库对象及内容。当执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的⼀个新的对象中,就位于 “.git/objects” 目录下。
这样的话,我们看到,只要能拿到这个HEAD,就能拿到master这棵树,然后就能拿到某个文件具体修改的内容。就可以管控文件了。
3.4添加文件
添加文件 - - 场景一
在包含 .git 的目录下新建⼀个 ReadMe 文件,我们可以使用 git add 命令可以将文件添加到暂存区
添加一个或多个文件到暂存区
git add [file1] [file2] ...
添加指定目录到暂存区,包括子目录:
git add [dir]
添加当前目录下的所有文件改动到暂存区:
git add .
再使用 git commit 命令将暂存区内容添加到本地仓库中:
提交暂存区全部内容到本地仓库中:
git commit -m "message"
提交暂存区的指定⽂件到仓库区:
git commit [file1] [file2] ... -m "message"
注意 git commit 后⾯的 -m 选项,要跟上描述本次提交的 message,由用户自己完成,这部分内容绝对不能省略,并要好好描述,是⽤来记录你的提交细节,是给我们人看的。
git commit 命令执行成功后会告诉我们,1个文件被改动(就是我们新添加的ReadMe文件),插入了一行内容(ReadMe有一行内容)。
我们还可以多次 add 不同的文件,而只 commit 一次便可以提交所有文件,是因为需要提交的文件是通通被 add 到暂存区中,然后一次性 commit 暂存区的所有修改。
截止目前为止,我们已经更够将代码直接提交至本地仓库了。我们可以使用 git log 命令,来查看下历史提交记录。该命令显示从最近到最远的提交日志,并且可以看到我们 commit 时的日志消息
git log
我们最近一次提交就是添加了三个文件。
commit后面跟的一长串的内容 81966641bb6caad5861ad0b13f71ff7ee143d516 是每次提交的 commit id (版本号),Git 的 commit id 不是1,2,3……递增的数字,而是一个 SHA1 计算出来的一个非常大的数字,用十六进制表示。根据这个id就可以定位到每次的提交。
Author后面跟的是配置的name和email。
Date:提交的日期
Date下面就是这次提交的细节也打印出来了。
如果嫌输出信息太多,看得眼花缭乱的,可以试试给git log加上 --pretty=oneline 参数
git log --pretty=oneline
通过add,commit这两步我们可以看看对.git产生了那些变化
tree .git
首先可以看到确实新生成了一个index(暂存区),add之后的内容都是添加到暂存区里。
HEAD默认指向的master,我们可以看看是不是这样,然后也可以看看master里面的内容。
cat .git/HEAD
cat .git/refs/heads/master
打印出来你会发现,这个master里面存的就是我们最新一次提交的commit id。
之前我们也说过master其实存的并不是对象库中一个个git对象,而是git对象的索引。所以commit id其实就是对象库中其中一个git对象索引。
我们可以把commit id分成2部分,其前2位是文件夹名称,后38位是文件名称。
找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过 sha (安全哈希算法)加密过的文件,好在我们可以使用 git cat-file 命令来查看版本库对象的内容:
git cat-file -p [commit id]
可以看到add 3 file就是我们最新提交的描述信息
parent 是上一次提交的commit id
tree后面也跟了一串,打印出来看到,都是我们之前提交过的文件,每个文件对应一个commit id,我们也可以使用统一的方式查看对应的内容,看到这个正是我们对ReadMe文件的修改。
总结⼀下,在本地的 git 仓库中,有几个文件或者目录很特殊
- index: 暂存区, git add 后会更新该内容。
- HEAD: 默认指向 master 分支的⼀个指针。
- refs/heads/master: 文件里保存当前 master 分支的最新 commit id 。
- objects: 包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。
添加文件 - - 场景二
我们已经清楚了如何向仓库中添加文件,并且对于工作区、暂存区、版本库也有了⼀定的认识。那么我们再展示⼀种添加文件的场景,能加深对工作区、暂存区、版本库的理解。
- 新增file4文件
- 将file4添加到暂存区
- 新增file5文件
- 提交修改
提交后发现打印了 1 file changed, 0 insertions(+), 0 deletions(-) ,意思是只有一个文件改变了,这时我们提出了疑问,不是新增了两个文件吗?
再来回忆下, git add 是将文件添加到暂存区, git commit 是将暂存区的内容添加到本地仓库中。由于我们并没有使用 git add file5 ,file5 就不在暂存区中维护,所以我们 commit 的时候其实只是把已经在暂存区的 file4 提交了,而遗漏了工作区的 file5。如何提交 file5 呢?很简单,再次add , commit 即可
3.5修改文件
Git 比其他版本控制系统设计得优秀,因为 Git 跟踪并管理的是修改,而非文件。从哪里可以得到这句话呢?我们在之前说的对象库,修改的工作区内容会写入对象库的一个新的git对象中,由这里也可以得到Git 跟踪并管理的是修改,而非整个文件。
什么是修改?比如你新增了⼀行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建⼀个新文件,也算一个修改。
让我们将 ReadMe 文件进行一次修改:
目前在工作区对 ReadMe 文件进行了修改,此时,仓库中的 ReadMe 和我们工作区的 ReadMe 是不同的,如何查看当前仓库的状态呢? git status 命令用于查看在你上次提交之后到目前是否有对文件进行再次修改。
git status
上面的结果告诉我们,ReadMe 被修改过了,但还没有完成添加与提交。
目前,我们只知道文件被修改了,但是具体哪些地方被修改了我们并不知道,可能你会说刚才修改的我们知道啊。可是,你还记得你三天前写了什么代码吗?或者没写?
git diff [file] 命令用来显示暂存区和工作区文件的差异,显示的格式正是Unix通用的diff格式。
git diff ReadMe
a代表改动前,b代表改动后
— 代表改动前,+++代表改动后
-代表改动前,-1表示第一行是改动前
+代表改动后,+1,2表示改动后的第一行开始连续两行的内容。
也可以使用 git diff HEAD – [file] 命令来查看版本库和工作区文件的区别。
git diff HEAD --ReadMe
知道了对 ReadMe 做了什么修改后,再把它提交到本地仓库就放心多了。
git add 之后,就没有看到上⾯ no changes added to commit (use “git add”
and/or “git commit -a”) 的消息了。接下来让我们继续 git commit 即可
3.6版本回退
之前我们也提到过,Git 能够管理文件的历史版本,这也是版本控制器重要的能力。
比如说如果有一天你发现之前的工作做的出现了很大的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
执行 git reset 命令用于回退版本,可以指定退回某一次提交的版本。要解释⼀下 “回退” 本质是要将版本库中的内容进行回退 ,工作区或暂存区是否回退由命令参数决定:
git reset 命令语法格式为:
git reset [--soft | --mixed | --hard] [HEAD]
-
–soft 参数对于工作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
-
–mixed 为默认选项,使用时可以不用带该参数。该参数将暂存区的内容和版本库退回为指定提交版本内容,工作区文件保持不变。
-
–hard 参数将工作区和暂存区和版本库都退回到指定版本。切记作工区有未提交的代码时不要用这个命令,因为工作区会回滚,你没有提交的代码就再也找不回了,所以使用该参数前⼀定要慎重。
HEAD 说明:
- 可直接写成 commit id,表⽰指定退回的版本
- HEAD 表示当前版本
- HEAD^ 上⼀个版本
- HEAD^^ 上上⼀个版本
- 以此类推…
可以使用 〜数字表示:
- HEAD~0 表示当前版本
- HEAD~1 上⼀个版本
- HEAD~2 上上⼀个版本
- 以此类推…
最新一次提提交是修改ReadMe也就是新增一个hello world。最早一次是add first file这一次提交是创建ReadMe后新增hello git。
接下来我们想回退到只有hello git的ReadMe,可以看到我们确实已经回退了只提交hello git的ReadMe的版本,后面的我们都看不到了。
如果突然后悔回退了怎么办?还可以回到之前吗?
我们可以继续使用 git reset 命令,回退到有hello world的ReadMe文件 版本,但我们必须要拿到 有hello world的ReadMe 的 commit id 去指定回退的版本。
但我们看到了 git log 并不能打印出 有hello world的ReadMe文件 的 commit id ,运气好的话我们可以从终端上去找找之前的记录,运气不好的话 commit id 已经被我们搞丢了=。=
其实Git 还提供了⼀个 git reflog 命令能补救⼀下,该命令用来记录本地的每⼀次命令。
git reflog
可以看到这里是一个短的commit id,它其实就是commit id的一部分,但是我们照样可以使用这一部分commit id进行回退。
可往往是理想很丰满,现实很骨感。在实际开发中,由于长时间的开发了,导致 commit id 早就找不到了,可突然某⼀天,我又想回退到 有hello world的ReadMe文件,那该如何操作呢?貌似现在不可能了。。。
值得说的是,Git 的版本回退速度非常快,因为 Git 在内部有个指向当前分支(此处是master)的HEAD 指针, refs/heads/master 文件里保存当前 master 分支的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储一个特定的version,可以简单理解成如下示意图:
3.7撤销修改
如果我们在我们的工作区写了很长时间代码,越写越写不下去,觉得自己写的实在是垃圾,这个时候我们想将新写的代码进行一个撤销操作,也就是想恢复到上一个版本。
对于撤销操作有不同的场景,也对应不同的操作。
情况一:对于工作区的代码,还没有 add
如果你写的代码比较少,你当然可以直接删掉你目前在工作区新增的代码。但是要是你写了3天,一直都没有提交,该怎么删掉呢?你自己都忘了自己新增过哪些,有人可能说,我可以 git diff xxx ⼀下,看看差别在删啊,那你肯定又要花3天时间删代码了,并且很大的概率还会改出bug。一周过去了,你怎么向你的老板交代呢?
Git 其实还为我们提供了更好的方式,我们可以使用 git checkout – [file] 命令让工作区的文件回到最近一次 add 或 commit 时的状态。 要注意 git checkout – [file] 命令中的-- 很重要,切记不要省略,一旦省略,该命令就变为其他意思了,后面我们再说。
git checkout -- [file]
执行这个命令之后发现我们新增的xxx code已经不在了。
情况二:已经 add ,但没有 commit
add 后还保存到了暂存区,怎么撤销呢?(工作区和暂存区同时保存了这个代码)
查看当前仓库状态,说明当前工作区和暂存区同时有这个代码,但是还没有commit 提交。
那如何将工作区和暂存区想要撤销的代码撤销呢?
让我们来回忆一下学过的 git reset 回退命令,该命令如果使用 --mixed 参数,可以将暂存区的内容退回为指定的版本内容,但工作区文件保持不变。那我们就可以回退下暂存区的内容了!!!
可以看到git status打印出来的没有暂存区的内容需要被commit提交了。所以我们现在的修改只存在于工作区,那我们和上面操作一样,撤销工作区修改就行了。
情况三:已经 add ,并且也 commit 了
不要担心,我们可以 git reset --hard HEAD^ 回退到上⼀个版本!不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后面会讲到远程版本库,一旦你推送到远程版本库,你就真的惨了……
3.8删除文件
在 Git 中,删除也是一个修改操作,如果要删除 file5 文件,怎么搞呢?
可以直接使用 rm 指令删除file5,但是它只是针对工作区进行删除,对于本地仓库file5并没有删掉。这导致工作区和版本库就不一致了,所以要删文件,除了要删工作区的文件,还要清除版本库的文件。才能完成一个文件在工作区、暂存区和版本库的删除操作。
上面我们一共进行了三步操作,其实我们可以只用2步就可以完成删除操作。
git rm [file]
删除工作区和暂存区的文件,我们只需要在commit一下就可以删除版本库的了。