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 | $ pwd |
pwd
命令用于显示当前的目录。在我的Ubuntu中,这个仓库位于/Users/Samxander/learngit
.
step 2: 通过 git init
命令把这个目录变成Git可以管理的仓库:
1 | $ git init |
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库。
step 3: 把文件添加到版本库
所有的版本控制系统,只能跟踪文本文件的改动,而无法跟踪图片和视频这类二进制文件(Word也是二进制格式)。
现在编写一个 readme.txt
文件,放在 learngit
目录下或子目录下。内容如下:
1 | Git is a version control system. |
特殊地,为创建这个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 | Git is a distributed version control system. |
随后运行 git status
1 | $ git status |
命令输出告诉我们,readme.txt
被修改过了,但还没有准备提交的修改。
如果想看看具体修改了什么,可以使用 git diff
查看修改了什么内容。
1 | $ git diff readme.txt |
可以从上面的命令输出看到,我们在第一行添加了一个distributed
单词。
知道了对readme.txt
作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add
:
1 | $ git add readme.txt |
然后我们运行git status
查看当前仓库的状态:
1 | $ git status |
git status
告诉我们,将要被提交的修改包括readme.txt
,下一步,就可以放心地使用 git commit
提交了:
1 | $ git commit -m "add distributed" |
提交后,我们再用git status
命令看看仓库的当前状态:
1 | $ git status |
版本回退
(练习:将第二行加上GPL,并提交)
现在共进行了三个版本的提交,分别是 wrote a readme file
, add distributed
, append GPL
.
在实际工作中,版本控制系统肯定有命令可以告诉我们历史记录。在Git中,我们用 git log
查看:
1 | $ git log |
git log
命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL
,上一次是add distributed
,最早的一次是wrote a readme file
。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:
1 | $ git log --pretty=oneline |
好了,现在我们启动时光穿梭机,准备把readme.txt
回退到上一个版本,也就是add distributed
的那个版本,怎么做呢?
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交9e000ba1df429c0aa9d972325d9847368ed1c584
, 上一个版本是HEAD^
,上上一个版本是HEAD^^
,往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
现在,我们要把当前版本append GPL
回退到上一个版本add distributed
,就可以使用git reset
命令:
1 | $ git reset --hard HEAD^ |
注意:--hard
会回退到上个版本的已提交状态,而--soft
会回退到上个版本的未提交状态,--mixed
会回退到上个版本已添加但未提交的状态。现在,先放心使用--hard
。
现在看看readme.txt
的内容是不是版本 add distributed
:
1 | $ cat readme.txt |
果然被还原了。
让我们用git log
再看看现在版本库的状态:
1 | $ git log |
最新的那个版本append GPL
已经看不到了。若要回到那个版本,只要上面的命令行窗口还没有被关掉,就可以找到那个 append GPL
的 commit id
是 9e000ba1...
,于是就可以指定回到未来的某个版本:
1 | $ git reset --hard 9e000ba1 |
再查看readme.txt
的内容:
1 | $ cat readme.txt |
若回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。当用$ git reset --hard HEAD^
回退到add distributed
版本时,再想恢复到append GPL
,就必须找到append GPL
的commit id。Git提供了一个命令git reflog
用来记录你的每一次命令:
1 | $ git reflog |
工作区和暂存区
工作区
个人理解,工作区就是电脑里面能直接看到的目录。例如创建的 learngit
文件夹就是一个工作区。
版本库
工作区里有一个隐藏的目录 .git
,这不算工作区,而是Git的版本库。这里面存了很多东西,其中最重要的就是称为 stage
的暂存区,还有Git自动创建的第一个分支master
,以及指向master
的一个指针 HEAD
。
git add
命令实际上就是把要提交的所有修改放到暂存区,然后执行 git commit
就可以一次性地把暂存区的所有修改提交到分支。
实践验证:
先对 readme.txt
做出修改:在后面添加一行内容:
1 | Git is a distributed version control system. |
然后,在工作区新建一个 LICENSE
文本文件。
先用 git status
查看一下状态:
1 | $ git status |
Git说,readme.txt
被修改了,而 LICENSE
还从来没有被添加过,所以显示他是未跟踪的。
现在,使用两次 git add
,把 readme.txt
和 LICENSE
都添加后,用 git status
再查看一下:
1 | $ git status |
所以,git add
命令实际上就是把要提交的所有修改放到暂存区,然后执行git commit
就可以一次性把暂存区的所有修改提交到分支。
1 | $ git commit -m "understand how stage works" |
一旦提交后,如果没有对工作区做任何修改,那么工作区就是“干净”的:
1 | $ git status |
管理修改
Git跟踪并管理的是修改而非文件。若要提交二次修改,要遵循以下流程:
第一次修改 -> git add
-> 第二次修改 -> git add
-> git commit
撤销修改
场景1:当改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
。
场景2:当不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,使用版本回退,不过前提是没有推送到远程库。
删除文件
在Git中,删除也是一个修改操作。先添加一个新文件test.txt
到Git并提交:
1 | $ git commit -m "add test.txt" |
一般情况下,直接在文件管理器中把没用的文件删除,或者用rm
命令删除:
1 | $ rm test.txt |
这个时候,Git知道删除了文件,因此,工作区和版本库就不一致了,git status
命令会立刻告诉你哪些文件被删除了:
1 | $ git status |
现在有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
:
1 | $ git rm test.txt |
现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
1 | $ git checkout -- test.txt |
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
命令git rm
用于删除一个文件。如果一个文件已经被提交到版本库,那么永远不用担心误删。但是要小心,只能恢复文件到最新版本,会丢失最近一次提交后你修改的内容。