Samxander's home

You shall see the difference now that we are back again!

0%

Git初步学习

Git入门学习

Git 是一种 分布式版本控制系统,主要用于管理源代码的版本历史。它能记录文件的每一次改动,让开发者能够随时回溯、更改和协作,从而极大提高了代码开发的效率和安全性。

如果把代码开发比作写一本书,Git 就像一本“时间机器”,能保存每一版的草稿,不小心删掉的内容可以找回来,还能让多人同时编辑不同的章节,最后合并在一起。


安装Git

本人使用Ubuntu 22.04,直接通过如下代码安装Git:

1
sudo apt-get install git

创建版本库

step 1: 我在/下使用如下命令创建空目录 learngit:

1
$ mkdir learngit

然后进入这个目录:

1
$ cd learngit

然后可以打印工作目录(print working directory)

1
2
$ pwd
/Users/Samxander/learngit

pwd 命令用于显示当前的目录。在我的Ubuntu中,这个仓库位于/Users/Samxander/learngit.

step 2: 通过 git init 命令把这个目录变成Git可以管理的仓库:

1
$ git init

瞬间Git就把仓库建好了,而且告诉你是一个空的仓库。

step 3: 把文件添加到版本库

所有的版本控制系统,只能跟踪文本文件的改动,而无法跟踪图片和视频这类二进制文件(Word也是二进制格式)。

现在编写一个 readme.txt 文件,放在 learngit目录下或子目录下。内容如下:

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

特殊地,为创建这个txt文件,我使用的是 Vim 。首先在终端输入如下代码(在learngit目录下!!):

1
$ vim readme.txt

随后按下 i 键进入插入模式,随后输入内容。输入完成后,按下 Esc 键退出插入模式,输入 :wq 保存并退出。

用命令 git commit 告诉Git,把文件提交到仓库:

1
$ git commit -m "wrote a readme file"

注意:-m 后面输入的是本次提交的说明,可以输入任意内容。内容最好是有意义的,这样就能从历史记录里方便地找到改动记录。

git commit命令执行成功后会告诉你,1 file changed:1个文件被改动(我们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。


时光机穿梭

我已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了。于是,我继续修改readme.txt文件,改成如下内容:

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

随后运行 git status

1
$ git status

命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

如果想看看具体修改了什么,可以使用 git diff 查看修改了什么内容。

1
2
3
4
5
6
7
8
9
10
$ git diff readme.txt 

diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 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.

可以从上面的命令输出看到,我们在第一行添加了一个distributed单词。

知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add

1
$ git add readme.txt

然后我们运行git status查看当前仓库的状态:

1
2
3
4
5
6
$ git status

位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: readme.txt

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

1
$ git commit -m "add distributed"

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

1
2
3
4
$ git status

位于分支master
无文件要提交,干净的工作区

版本回退

(练习:将第二行加上GPL,并提交)

现在共进行了三个版本的提交,分别是 wrote a readme file, add distributed, append GPL.

在实际工作中,版本控制系统肯定有命令可以告诉我们历史记录。在Git中,我们用 git log 查看:

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

commit 9e000ba1df429c0aa9d972325d9847368ed1c584 (HEAD -> master)
Author: Samxander <weijiazhe123@mail.nwpu.edu.cn>
Date: Mon Nov 25 18:38:53 2024 +0800

append GPL

commit d7c8172e14e38f27ccb901e01bf3c7e4eee8c35f
Author: Samxander <weijiazhe123@mail.nwpu.edu.cn>
Date: Mon Nov 25 18:30:46 2024 +0800

add distributed

commit 0998895744bfbd854f6d74792da039c0d3b2c7de
Author: Samxander <weijiazhe123@mail.nwpu.edu.cn>
Date: Mon Nov 25 17:25:26 2024 +0800

wrote a readme file

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

1
2
3
4
5
$ git log --pretty=oneline

9e000ba1df429c0aa9d972325d9847368ed1c584 (HEAD -> master) attend GPL
d7c8172e14e38f27ccb901e01bf3c7e4eee8c35f add distributed
0998895744bfbd854f6d74792da039c0d3b2c7de wrote a readme file

好了,现在我们启动时光穿梭机,准备把readme.txt回退到上一个版本,也就是add distributed的那个版本,怎么做呢?

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交9e000ba1df429c0aa9d972325d9847368ed1c584 , 上一个版本是HEAD^,上上一个版本是HEAD^^,往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

现在,我们要把当前版本append GPL回退到上一个版本add distributed,就可以使用git reset命令:

git
1
2
3
$ git reset --hard HEAD^

HEAD 现在位于 d7c8172 add distributed

注意:--hard会回退到上个版本的已提交状态,而--soft会回退到上个版本的未提交状态,--mixed会回退到上个版本已添加但未提交的状态。现在,先放心使用--hard

现在看看readme.txt 的内容是不是版本 add distributed:

1
2
3
4
$ cat readme.txt

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

果然被还原了。

让我们用git log再看看现在版本库的状态:

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

commit d7c8172e14e38f27ccb901e01bf3c7e4eee8c35f (HEAD -> master)
Author: Samxander <weijiazhe123@mail.nwpu.edu.cn>
Date: Mon Nov 25 18:30:46 2024 +0800

add distributed

commit 0998895744bfbd854f6d74792da039c0d3b2c7de
Author: Samxander <weijiazhe123@mail.nwpu.edu.cn>
Date: Mon Nov 25 17:25:26 2024 +0800

wrote a readme file

最新的那个版本append GPL已经看不到了。若要回到那个版本,只要上面的命令行窗口还没有被关掉,就可以找到那个 append GPLcommit id9e000ba1...,于是就可以指定回到未来的某个版本:

1
2
3
$ git reset --hard 9e000ba1

HEAD 现在位于 9e000ba attend GPL

再查看readme.txt 的内容:

1
2
3
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.

若回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?

在Git中,总是有后悔药可以吃的。当用$ git reset --hard HEAD^回退到add distributed版本时,再想恢复到append GPL,就必须找到append GPL的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:

1
2
3
4
5
6
7
$ git reflog

9e000ba (HEAD -> master) HEAD@{0}: reset: moving to 9e000ba1
d7c8172 HEAD@{1}: reset: moving to HEAD^
9e000ba (HEAD -> master) HEAD@{2}: commit: attend GPL
d7c8172 HEAD@{3}: commit: add distributed
0998895 HEAD@{4}: commit (initial): wrote a readme file

工作区和暂存区

工作区

个人理解,工作区就是电脑里面能直接看到的目录。例如创建的 learngit 文件夹就是一个工作区。

版本库

工作区里有一个隐藏的目录 .git,这不算工作区,而是Git的版本库。这里面存了很多东西,其中最重要的就是称为 stage暂存区,还有Git自动创建的第一个分支master,以及指向master的一个指针 HEAD

git add 命令实际上就是把要提交的所有修改放到暂存区,然后执行 git commit就可以一次性地把暂存区的所有修改提交到分支。

实践验证:

先对 readme.txt 做出修改:在后面添加一行内容:

1
2
3
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.

然后,在工作区新建一个 LICENSE 文本文件。

先用 git status 查看一下状态:

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

位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: readme.txt

未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
LICENSE

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

Git说,readme.txt 被修改了,而 LICENSE 还从来没有被添加过,所以显示他是未跟踪的

现在,使用两次 git add,把 readme.txtLICENSE 都添加后,用 git status 再查看一下:

1
2
3
4
5
6
7
$ git status

位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
新文件: LICENSE
修改: readme.txt

所以,git add命令实际上就是把要提交的所有修改放到暂存区,然后执行git commit就可以一次性把暂存区的所有修改提交到分支。

1
2
3
4
5
$ git commit -m "understand how stage works"

[master d25e97f] understand how stage works
2 files changed, 1 insertion(+)
create mode 100644 LICENSE

一旦提交后,如果没有对工作区做任何修改,那么工作区就是“干净”的:

1
2
3
4
$ git status

位于分支 master
无文件要提交,干净的工作区

管理修改

Git跟踪并管理的是修改而非文件。若要提交二次修改,要遵循以下流程:

第一次修改 -> git add -> 第二次修改 -> git add -> git commit


撤销修改

场景1:当改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

场景2:当不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,使用版本回退,不过前提是没有推送到远程库。


删除文件

在Git中,删除也是一个修改操作。先添加一个新文件test.txt到Git并提交:

1
2
3
4
5
$ git commit -m "add test.txt"

[master a511415] add test.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt

一般情况下,直接在文件管理器中把没用的文件删除,或者用rm命令删除:

1
$ rm test.txt

这个时候,Git知道删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:

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

位于分支 master
尚未暂存以备提交的变更:
(使用 "git add/rm <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
删除: test.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

现在有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit

1
2
3
4
5
6
7
8
9
$ git rm test.txt

rm 'test.txt'

$ git commit -m "remove test.txt"

[master 67c1822] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt

现在,文件就从版本库中被删除了。

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

1
$ git checkout -- test.txt

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么永远不用担心误删。但是要小心,只能恢复文件到最新版本,会丢失最近一次提交后你修改的内容


远程仓库

Insist on writing original high-quality articles. Your support is my biggest motivation.