新的学期开始新的项目,一个习惯了科研的开发小白也要开始学git了o(╥﹏╥)o,文章都是大白话,,主要是为了记录自己的学习史~
文章结构
一、Git简介
Git:世界上最先进的分布式版本控制系统
- 什么是版本控制系统?
- 既然有分布式,肯定也有集中式,分布式有什么优势使得Git风靡全球。
1、什么是版本控制
先来解决第一个问题,举一个例子,我们现在在写论文,写完交给老板,boss说写的和shit一样,改!好我们写第二个版本,直接在第一版的基础上写吗?显然不是,当然要另起炉灶,万一你写的更像shit还能重用第一版,写完第二个版本,老板说你这次写的比shit强一点,再改,然后我们写第三个版本,最后。。。
过了一周,你想起来某个版本里写了一个很重要的公式忘了复制,但是已经记不清删除前保存在哪个文件里了,只好一个一个文件去找,真麻烦。看着一堆乱七八糟的文件,想保留最新的一个,然后把其他的删掉,又怕哪天会用上,还不敢删,真郁闷。老板看不下去了,和你一起改,他改好了你也改好了,此时,你必须想想,发给她之后到你收到她的文件期间,你作了哪些改动,得把你的改动和她的部分合并,真困难。但是!21世纪到了,我们结束了手动管理多个“版本”的史前时代,进入到版本控制的的年代,也就是说,版本控制软件不但能自动帮我记录每次文件的改动,还可以让boss协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里瞄一眼就可以,这就是版本控制–自动的控制文件的多个版本。
2、什么是分布式版本控制?
先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
当然,要到服务器我们必须有网,而且网速要快,万一你网速10k/s,传一个视频得把人憋死。
而分布式控制系统没有中央服务器!没有中央服务器!没有中央服务器!每个人都是自己的中央服务器,拥有完整的版本信息。这时你可能要问了?那如果两个人都修改了一个文件怎么办?其实只要双方互相推送这个信息就可以了,往往,分布式系统也有一个“中央服务器”,但是这个服务器只是为了大家交换信息,没有非常重要,由此可见,分布式控制安全性很高(版本库无处不在,坏一个无所谓),而且不用联网,当然还有很多其他好处。
二、Git安装
我使用的是windows,所以linux,Mac的兄弟姐妹对不住了,不会。
- 在Git官网下载应用程序。你会看到下图,然后无脑next即可,耐心等待x分钟
- 安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
- 安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "zhangSan"
$ git config --global user.email "email@example.com"
因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。你也许会担心,如果有人故意冒充别人怎么办?这个不必担心,首先我们相信大家都是善良无知的群众,其次,真的有冒充的也是有办法可查的。
注意git config
命令的--global
参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址
三、创建版本库
什么是版本库呢?你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:
pwd
显示当前目录
- 作为一个c盘爱护者,我很讨厌把东西放在C盘,于是我们
cd E:
,然后创建一个叫做GitRepository
的文件夹,再次cd,就找到了自己喜欢的位置(不要用中文!不要用中文!不要用中文!)
git init
命令,将该目录变成你的仓库
瞬间Git就把仓库建好了,注意这个.git的目录是Git来跟踪管理版本库的,不要乱改!不要乱改!不要乱改!
如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah
命令就可以看见。
四、把文件添加到版本库
所有的版本控制系统只能跟踪文本文件,比如TXT文件,网页,所有的程序代码等等。图片,视频这些文件。。。emmmmmm只能知道他大小变化了多少,而且word也不算是文本文件,必须是纯文本!纯文本!纯文本!
还有一点,建议大家不要用记事本,太恶心了,如果用记事本编辑文件,你将会体验到想死的感觉。建议下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可:
言归正传,现在我们编写一个readme.txt
文件,内容如下:
Hello world! I am Git!
一定要放到GitRepository目录(也就是你刚才init的目录)下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。然后,开始操作
- 第一步,用命令
git add readme
告诉Git,兄弟,我把这个文件放到你那里了。如果没有报错那你就成功了,这里可能会有几个小问题,没有进入readme
所在的文件夹或者后缀打错了,稍微注意。。
- 第二步,用命令
git commit
告诉Git,可以把文件提交到仓库了:
-m
后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
git commit
命令执行成功后会告诉你,1 file changed
:1个文件被改动(我们新添加的readme文件);1 insertions
:插入了1行内容
看到这里你可能会想,为什么我们需要两步?我直接commit不是很好嘛?其实我们一次可以add
超多文件,然后一个commit
一次性提交。
$ git add f1.txt
$ git add f2.txt f3.txt
$ git commit -m "add 3 files."
五、版本回退
1、工作区和暂存区,版本库
有很多版本控制工具都会有工作区的概念,Git与众不同的点在于他加入了暂存区并有一个工作仓库
-
工作区
所谓的工作区也就是你的目录,比如我刚才创建的GitRepository
文件夹。 -
版本库
还记得刚才创建版本库init
之后生成的.git
文件吗,他虽然是文件,但不是工作区,他被称之为版本库,存储着很多东西,其中最重要的叫做**stage(index)**的暂存区,和Git自动为我们创建的工作仓库repository
,以及指向repository
的指针HEAD
。
在我们刚才的操作中,需要提交的文件修改通通放到暂存区,然后一次性的commit
暂存区的所有修改。也就是说git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交工作仓库。而工作区保存的始终是你放进去的文件。
2、回到过去,从过去回到未来。
每次我们修改了文件,都需要重新add
,commit
。也就是说我第二版论文写好了,commit
一下,如果我们之后改乱了或者误删了,可以从最近的commit
进行恢复,而不用从头开始。当然,我们总不能用人脑来记录我们啥时候改了啥,使用git log
,查询历史记录。
该命令显示从近到远的提交日志,我一共提交了两次,最后的readme
是这样的。
Hello world! I am Git!
Your paper likes rubbish!
现在我想做的是将readme
回退到只有第一行的那个版本,how to do it?
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
。
git reset
是重中之重,
--hard
参数有啥意义?看看这里,再看看readme
他果然是被还原了。
回退是成功了,可是如果我们后悔了呢?我们不想回退了,我们想找回未来,此时再次git log
,已经没有boss’s comment的版本信息了,但是办法还是有的
我们可以顺着窗口网上一直找,直到找到那个版本的commit
编号,比如下图中的 7cf8cf34...
,
根据这个编号,我们再次进行hit reset --hard num
他又回到了这个版本,是不是很神奇(ps:版本号5位即可,只要在多个版本号中可以区分)
小结一下
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard <commit_id>
。- 穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
六、管理修改
我们先要知道什么是修改?比如你新增了一行,删除了一行,更改了某些字符,删了一些又加了一些,甚至创建一个新文件,都算一个修改。
而Git
之所有比其他版本控制系统强的原因就在于,Git管理并跟踪的是修改,而不是文件。为什么?我们看个实例
- 首先我们对
readme
进行修改,现在他是这样的
Hello boss! I am yfZhang!
boss: Your paper likes rubbish!
- 然后添加
- 然后我们再增加一行,使
readme
变成这样
Hello boss! I am yfZhang!
boss: Your paper likes rubbish!
rewrite! rewrite! rewrite!
- 然后我们直接提交
这不完犊子嘛,未暂存的更改未提交
,也就是说我们第二次的修改并没有放入暂存区(我们第二次修改后没有git add
操作,也就是第二次修改没有加入暂存区,所以第一次的修改被提交了,而第二次的修改并没有)。
那怎么提交第二次修改呢?你可以继续git add
再git commit
,也可以别着急提交第一次修改,先git add
第二次修改,再git commit
,就相当于把两次修改合并后一块提交了,提交完之后你的暂存区应该就空了
七、撤销修改
某天,你改论文改到凌晨两点,不小心将readme
写成了这样,
Hello boss! I am yfZhang!
boss: Your paper likes rubbish!
rewrite! rewrite! rewrite!
My boss is stupid!
不过好在你人品爆发突然看到了这大不敬的话语,那么要如何撤销呢?刚才我们使用git status
的时候其实出现过这样一张图
他告诉我们 git restore <file>
可以丢弃工作区的修改,让我们试一试
果然我们取消了不妙的修改。当然这里我们还并没有add
操作。
到了凌晨三点,你怒火攻心,写下了
Hello boss! I am yfZhang!
boss: Your paper likes rubbish!
rewrite! rewrite! rewrite!
My stupid boss know nothing!
并且还执行了git add
,不过在commit
之前,你还是觉得不太妙,准备撤销。
此时中断提醒我们使用git restore --staged <file>
命令,不妨试一试
此时会尴尬的发现,他并没有删掉,但是直觉告诉我们事情没有这么简单,不妨再来看看git status
诶,他已经不在暂存区,而是回到工作去了,changes not staged for commit
表示还没有进入暂存区。那我们就可以和之前没有add
时一样,使用git restore readme
操作进行修改。
撤销成功!
小结一下
- 如果我们写了不好的东西,还没有
add
,直接使用git restore <file>
进行撤销。 - 如果我们写了不好的东西,还
add
了,先使用git restore --staged <file>
移除暂存区再使用git restore <file>
移除工作区。 - 如果已经
commit
了,想要撤销提交,只能退回之前的版本,但是如果你已经推送到远程库(之后再说远程库),那就只能希望boss眼神不好了。
八、删除文件
在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test到Git并且提交:
如果我们直接在文件目录下吧文件删除了,Git是知道这个操作的
正如我们修改了文件,即使没有add
,git status
也能反应出来。此时如果铁了心了要删除,就使用git rm
命令,并且git commit
,并且并且并且!!!
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:git checkout -- test