Git和Github的基本使用

果然人还是要工作的啊

Git

什么是Git

Git是目前世界上最先进的分布式版本控制系统。

分布式:

既然有分布式,自然就会有集中式。SVN就是集中式版本控制系统,其特点是版本库集中放置在中央服务器里,需要修改工程时,需要先从服务器里下载版本信息。工作完成后,需要再把版本信息推送回中央服务器。

这样,工作时必须要联网。

而Git不同,Git在每台主机里都有自己完整的版本信息库,多人协作时,只需要把自己在本地所作的修改推送给对方,就可以互相知道对方所作的更改了。

版本控制系统:

每一次更改工程时都使用Git做一次记录,Git就会记住你更改了什么内容。

需要退回到某个版本时,也可以方便地使用Git来回退。

下载git

https://git-scm.com/download/

Linux可以使用gpt-get install git下载

设置用户信息和邮箱

当我们对工程进行一些改动的时候,我们需要使用用户名和邮箱来作为标识,让其它人看到之后知道这些代码是被谁所改动的。

设置用户名和邮箱

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

查看当前Git登录的用户名和邮箱

$ git config --global user.name $ git config --global user.email

开始使用Git

初始化

从终端进入到想要记录的文件里,输入

1
$ git init

这时候如果该文件是空的,终端执行指令时会输入一句提示语,不影响程序执行。

执行完该指令,可以看到文件夹内部多了一个.git的隐藏文件夹

.git文件夹是git init后在当前目录生成的一个管理git仓库的文件夹,这里包含所有git操作所需要的东西

添加文件

我们在原文件夹下,添加一个文件a.txt,在里面随便写一些东西。

在刚刚的终端输入

1
$ git add a.txt

如果命令成功执行,不会有任何提示信息。

这时我们只是把文件添加到了仓库缓存区,想要正式提交到仓库,我们需要使用commit命令:

1
$ git commit -m "添加了a"

-m后面的信息是我们对于该版本的描述信息,该指令成功执行后,会输出一些提示信息,大体内容就是我们的描述信息,我们的版本做了哪些改动等等

1
2
3
[master (root-commit) 494001b] 添加了a
1 file changed, 2 insertions(+)
create mode 100644 a.txt

之所以每次更新仓库需要add和commit两步,就是因为我们add可以添加多个文件,可以每次写完一个文件就add一次,也可以一次add多个文件。到最后,工作告一段落了,我们就可以统一一次commit把前面add的文件都提交

修改文件

当我们需要修改某个文件时,先修改,修改之后,同样把修改过的文件使用add指令加进来,之后还是commit就可以了

比如我在上面的基础上,添加了b.txt和c.txt两个文件,并把a.txt里面的内容做了一些修改,我们就打开终端,输入:

1
2
$ git add a.txt b.txt c.txt
$ git commit -m "新增了b.txt和c.txt;修改了a.txt的内容"

查看版本状态

假设我们的工程出现了一些问题,某个原本正常的功能经过我们的修改之后不正常了。我们现在想要把它回溯到正常的那个版本,但由于已经做了巨量的版本更改,忘记了具体是哪个了,这时,我们打开终端,输入

1
$ git log

这会显示出我们所有的版本记录

图中可以看到Git显示版本的格式,首先会把我们当前的版本列在最上面,然后按照时间顺序,由近到远。

每个版本的描述信息中,首先是一串十六进制数的版本id,这串id是我们找回版本的唯一凭据。之后是作者信息和更新时间,最后是我们自己写的版本描述信息。

Git使用HEAD表示当前的版本,上一个版本记为HEAD^,再上一个记为HEAD^^,上一百个可以用简洁的方法表示为HEAD^100

回到历史版本

查看并不能解决我们的问题,我们需要把工程回到历史上那个能用的版本

我们可以通过版本号来回溯,输入

1
$ git reset --hard <版本id>

如果知道回溯的版本是向上回溯几个版本的话,比如回溯到上一个版本,可以把版本号换为对应的HEAD^

回溯成功后,文件夹中的内容也回到了当时的状态

回到“未来”版本

书接上文,我们回溯到了历史版本,但我们又一次后悔了,想再回到当时出错的版本修改修改。如果你没有关闭命令行,里面保存这刚刚那一版本的id,我们仍然可以使用上面的reset命令回去。

但如果我们的命令行里已经没有刚刚的命令记录了,这时查看git log已经没有当时版本的id号了,是不是就回不去了呢?

不是的,我们依然可以使用

1
$ git reflog

这里保存了我们之前操作的记录。使用前面的HEAD@{1}和c517112都可以回到当时的版本。

查看状态:理解工作区和暂存区

使用命令:

1
$ git status

查看当前的状态

图中第一次输入命令时,文件夹中未作任何改动

第二次输入命令之前,我打开了之前的a这个文本文档,添加了一句话,再次查看状态可以看到红色的modified字样

我们使用add命令将改动后的a添加进来,看到了绿色的modified字样

最后,我们使用commit提交修改,查看时又回到了未作改动的模样

这里我们提一下工作区和版本库的概念。

工作区:就是你在电脑上看到的目录,比如目录下testgit里的文件(.git隐藏目录版本库除外)。或者以后需要再新建的目录文件等等都属于工作区范畴。

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

使用git add把文件添加进去,实际上就是把文件添加到暂存区。

使用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支上。

工作区和暂存区的区别体现在下一节——撤销上

撤销修改

使用命令:

1
$ git checkout -- 文件名

可以撤销所有未保存到暂存区的修改

我把a.txt的内容改一下,改为:

然后将其add到暂存区

并在这之后,再往后面添加一段,点击记事本文件里的保存

然后使用命令后打开原来的文件:

可以看到文件回到了上次添加后的状态

删除文件

如果要删除文件,先在目录删掉之后,再使用rm指令,类似于add指令一样,将删掉的文件添加进来之后commit就可以了

若要恢复未被添加进暂存区的已删除文件,我们也需要使用reset命令,格式和上面一样。

分支

在前面的演示中,所有的提交都是只有一条时间线的,也称为一个分支。上面的演示都是在master(也称为主分支)中进行的。

前面说到HEAD指向最近提交的版本,但严格来说,HEAD指向的是当前分支

创建并切换到dev分支

使用:

1
$ git checkout -b dev

建立名为dev的分支,并切换到dev分支

使用

1
$ git branch

查看所有分支

当前分支会高亮显示并添加一个分号

我们在a.txt里面添加内容:

并commit,

此时如果你切回主分支,你是看不到刚刚的添加的

使用

1
$ git checkout master

切换回主分支

合并分支

我们可以把dev分支上的内容合并到分支master上了,可以在master分支上,使用如下命令

1
$ git merge dev

合并之后,主分支就能看见后面加的那几句话了

删除分支

合并之后,我们可以使用

1
$ git branch -d dev

删除dev分支

处理冲突

我们还是创建一个dev分支,并在a.txt下添加和master分支冲突的内容

切换回主分支,给a添加不一样的内容,造成冲突

然后合并:

无法合并,提示冲突

此时查看文件,可以看到冲突的位置:

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中<<<HEAD是指主分支修改的内容,>>>>>dev 是指dev上

分支管理策略

通常合并分支时,git一般使用”Fast forward”模式,在这种模式下,删除分支后,会丢掉分支信息

使用带参数-–no-ff来禁用”Fast forward”模式。

1
git merge --no-ff -m "使用-no-ff" dev

Github

注册账号

创建SSH Key

在用户主目录下(Windows电脑的C:\Users\用户名文件夹),看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果有的话,直接跳过这一步,

如果没有的话,打开命令行,输入如下命令:

1
ssh-keygen  -t rsa –C “youremail@example.com”

如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去;id_rsa.pub是公钥,可以放心地告诉任何人。

打开id_rsa.pub,复制里面的内容,登陆GitHub,打开“Account settings”,“SSH Keys and GPG keys”页面,然后,点“New SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容即可。

创建仓库

首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库

然后起一个项目名

来到这个项目的主页

可以看到主页提供了两种和本地仓库关联起来的方式

方法一:

把本地已有的同名Git仓库和GitHub上的仓库关联起来

我们在本地新建了一个名为Gittest的文件夹,之后执行

1
git init

将Gittest文件夹设置为Git仓库

然后添加文件,比如我们新写了一个hello.txt:

执行本地仓库的操作:

1
2
git add hello.txt
git commit -m "first commit"

到此为止已经提交到了本地仓库,接下来我们把本地仓库和远程仓库联系起来,执行:

1
2
git remote add origin git@github.com:MachinePlay/Gittest.git
git remote add <shortname> <url>

把上面的MachinePlay替换成你自己的GitHub账户名,否则,你在本地关联的就是的MachinePlay的远程库,关联没有问题,但是推送是推不上去的,因为SSH Key公钥不在他的账户列表中。

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库

下一步,就可以把本地库的所有内容推送到远程库上

1
git push -u origin master

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

此后git add git commit-m之后 就可以使用

1
git push origin master

就可以把自己的代码上传到远程仓库了。

方法二:

使用Git clone直接从远程仓库克隆下来

前面我们讲了先有本地库,后有远程库的时候,如何关联远程库。

现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。

首先,登陆GitHub,创建一个新的仓库,名字叫Gittest

每个仓库都有一个地址:

我们在本地使用git clone直接把远程仓库克隆下来。

1
git clonegit@github.com:MachinePlay/Gittest.git

查看远程库信息

1
git remote -v

删除远程库

1
git rm 远程库名

本文参考了https://www.jianshu.com/p/296d22275cdd

本文参考了https://www.cnblogs.com/tugenhua0707/p/4050072.html

https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E7%9A%84%E4%BD%BF%E7%94%A8