作者:下里巴人

来自南京审计大学

前言:

博主在业余时间一直在学习有关hexo博客框架的内容,发现git版本控制贯穿始终,而作为一个计算机小白,对此的接触仅限于我见到的教程里那些git命令,我对此并不了解。然后便打算开始跟着廖雪峰老师进行学习,本文是此次的学习记录,参照廖雪峰老师的教程,简单的复述一遍学习过程,有需要的自行取用哈^_^

什么是Git

  • Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
  • Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
  • Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

我们为什么要学习Git

对于这个问题,廖雪峰老师有一段很恰当例子,我引用在下面:

“如果你用Microsoft Word写过长篇大论,那你一定有这样的经历:想删除一个段落,又怕将来想恢复找不回来怎么办?有办法,先把当前文件“另存为……”一个新的Word文件,再接着改,改到一定程度,再“另存为……”一个新文件,这样一直改下去,最后你的Word文档变成了这样:”

过了一周,你想找回被删除的文字,但是已经记不清删除前保存在哪个文件里了,只好一个一个文件去找,真麻烦。看着一堆乱七八糟的文件,想保留最新的一个,然后把其他的删掉,又怕哪天会用上,还不敢删,真郁闷。更要命的是,有些部分需要你的财务同事帮助填写,于是你把文件Copy到U盘里给她(也可能通过Email发送一份给她),然后,你继续修改Word文件。一天后,同事再把Word文件传给你,此时,你必须想想,发给她之后到你收到她的文件期间,你作了哪些改动,得把你的改动和她的部分合并,真困难。于是你想,如果有一个软件,不但能自动帮我记录每次文件的改动,还可以让同事协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里瞄一眼就可以,岂不是很方便? 这个软件用起来就应该像这个样子,能记录每次文件的改动:

这样,你就结束了手动管理多个“版本”的史前时代,进入到版本控制的20世纪。

创建版本库(repository)

首先,在合适的地方创建一个空文件夹,将终端设置在该目录路径下,紧接着,通过git init命令,将该目录变成一个Git可以管理的仓库:

1
2
$ git init
Initialized empty Git repository in .........git/

就像为了我们之前所说的一样,为了避免各种各样奇奇怪怪的错误,我们所有的文件名尽量都不要掺杂英文

这时候我们会发现,当前目录下会多出来一个 .git 文件夹,看不到也没事,需要我们去设置一下,因为这个文件夹是默认隐藏的,无论如何这就代表我们成功啦!需要注意的是,这个文件夹我们最好不要手动修改,以防出现想象不到的错误。

设置用户名

为什么要设置用户名

因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。这一点可以参照我们hexo博客建立过程中的问题。一般来说,在完成Git下载后,我们需要声明全局用户名和邮箱,指令如下:

1
2
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置。当然,在我们之前的博文中有提到,如果我想部署两个博客在同一台电脑上,那么这个全局用户名就会起冲突,为了给不同的项目指定用户名和邮箱,我们可以将终端切至 .git 目录下,打开 config 配置文件,加入以下配置:

1
2
3
[user]
name = Yourname
email = email@example.com

这样,我们便给这个项目仓库指定了用户名与邮箱。

将自己的文件添加至仓库

这时,我们的仓库已经建立完成。我们可以现在建立文件并且添加至库中。首先,我们需要在主文件夹目录下 创建我们的项目。我们在这里创建一个readme.txt并在其中输入以下内容:

1
2
Git is a version control system.
Git is free software.

第一步,我们用如下指令将文件添加到仓库:

1
$ git add readme.txt

此时没有任何提升,便代表我们已经成功提交了

第二步,我们用如下指令将文件提交至仓库:

1
2
3
4
5
$ git commit -m"wrote a readme file"

[master (root-commit) ed42ada] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt

这里解释一下,-m后是本次提交的说明,这样你就能从历史记录里方便地找到改动记录。

我们发现,这两个命令似乎都是提交,那是不是有点多此一举?显然不是,git add命令可以多次添加文件,而git commit则可以一次提交多个文件,相当于一次版本改动,我需要修改多个文件,各个修改文件的提交都是由git add命令添加,最终用git commit命令完成一次版本的改动。

修改一次文件

首先,我们将我们建立的txt文件修改如下:

1
2
Git is a distributed version control system.
Git is free software.

这时,我们输入以下指令,来检查工作区状态:

1
2
3
4
5
6
7
8
9
$ git ststus

On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

上面的命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。如果这时我们想查看改文件究竟如何被修改呢?可以输入如下指令:

1
2
3
4
5
6
7
8
9
10
11
$ git diff

diff --git a/readme.txt b/readme.txt
index d8036c1..013b5bc 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
\ No newline at end of file

可以从上面的命令输出看到,我们在第一行添加了一个distributed单词。知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是:

1
$ git add readme.txt

这时,我们再输入git status看看当前仓库状态:

1
2
3
4
5
6
7
$ git status

On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt

git status告诉我们,将要被提交的修改包括readme.txt,下一步,就可以放心地提交了:

1
2
3
4
$ git commit -m"add distributed"

[master 3ea9a2c] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)

提交后,我们再用命令看看仓库的当前状态:

1
2
3
4
$ git status

On branch master
nothing to commit, working tree clean

Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。

版本回退

在此之前,我们再次修改一下文件,并且再次提交:

1
2
Git is a distributed version control system.
Git is free software distributed under the GPL.

这时就像我们打游戏存档一般,我们每次修改之后都提交了一次,到目前为止我们的版本迭代了几次呢?我们可以输入以下指令来查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git log

commit 48675df794edcb40b217c57ba978779411834462 (HEAD -> master)
Author: Motherlesssss <1169153079@qq.com>
Date: Fri Nov 25 23:32:45 2022 +0800

append GPL

commit 68a3c67b2d046e418869ef8bd683053de763595a
Author: Motherlesssss <1169153079@qq.com>
Date: Fri Nov 25 23:32:16 2022 +0800

add distributed

commit 7218bf93db606e27d824f4d7b86e1e782ae7a0e9
Author: Motherlesssss <1169153079@qq.com>
Date: Fri Nov 25 23:31:35 2022 +0800

wrote a readme file

这时我们可以看到我们有三次修改记录。这里值得一提的是,这里的commit后的便是自动生成的版本号,为十六进制。

首先我们必须要知道,在Git中,用HEAD表示当前版本,也就是最新的提交48675df794...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

这里我们要注意,在终端中输入git log后终端可能会出现下图的情况:

不必慌张,我们只需输入q ,即可解决这个问题

现在。我们要退回上一个版本,可以输入以下指令:

1
2
3
$ git reset --hard HEAD^

HEAD is now at 68a3c67 add distributed

这时我们可以发现,我们的文件已经变成了:

1
2
Git is a distributed version control system.
Git is free software.

恭喜,这时候我们已经成功还原,不过且慢,我们先来检查一下版本库的状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git log

commit 68a3c67b2d046e418869ef8bd683053de763595a (HEAD -> master)
Author: Motherlesssss <1169153079@qq.com>
Date: Fri Nov 25 23:32:16 2022 +0800

add distributed

commit 7218bf93db606e27d824f4d7b86e1e782ae7a0e9
Author: Motherlesssss <1169153079@qq.com>
Date: Fri Nov 25 23:31:35 2022 +0800

wrote a readme file

我们会发现,我们最新的那个版本已经不见了。但是这时我们后悔了,想要复原怎么办?不要着急。如果我们此时终端还在,你就可以顺着往上找啊找啊,找到那个append GPLcommit id48675df7...,于是就可以指定回到未来的某个版本:

1
2
3
$ git reset --hard 48675df7

HEAD is now at 48675df append GPL

版本号不需写全,只要前几位,Git会自动帮你匹配,当然要多几位,否则出现重复,就无法判断究竟是哪一个了。这时候我们看,我们的文件已经还原啦:

1
2
Git is a distributed version control system.
Git is free software distributed under the GPL.

当然,如果此时你退回到了某个版本,但是过了几天后你反悔了,此时你无法找到新版本的commit id,这时候也不要慌,我们输入一下指令:

1
2
3
4
5
6
7
8
$ git reflog

48675df (HEAD -> master) HEAD@{0}: reset: moving to 48675df7
68a3c67 HEAD@{1}: reset: moving to HEAD^
48675df (HEAD -> master) HEAD@{2}: commit: append GPL
68a3c67 HEAD@{3}: commit: add distributed
7218bf9 HEAD@{4}: commit: wrote a readme file

就如我们看到一般,我们要恢复某个版本,就必须找到对应的commit id,而Git提供git reflog命令,来记录你的每一次命令。这时我们可以看到,append GPLcommit id48675df。有了对应的commit id,我们便可以回到我们指定的版本啦!