Git

1、简介

Git就是一个分布式版本的控制工具软件。

工具软件:实现指定功能的软件,比如,说到下载,想到的就是迅雷,说到聊天,微信与qq

Git:可以管理软件开发项目中的源代码文件

版本控制:版本控制是一种记录文件内容变化,以便将来能够查阅特定版本修订情况的系统。版本控制其实最重要的是可以记录文件修改的历史记录,从而让用户能够查看历史版本,方便版本切换。

为什么需要版本控制?

个人开发过渡到团队协作。

本次课程会讲解如下内容:

Git安装

Git 命令:讲解git中常用的命令

Git分支: 分支特性,分支创建,分支转换,分支合并,代码合并冲突解决

GitHub: 创建远程库,代码推送(Push), 代码拉取(Pull) (由于网络的原因,会出现无法链接,或者是链接比较慢的情况)

Gitee 码云(服务器在国内,国内的GitHub

GitLab(公司自己搭建的项目管理的服务器)

官网:https://git-scm.com/

2、版本控制介绍

(1)集中式版本控制工具

CVS,SVN,VSS

集中化的般般控制系统诸如CVS,SVN等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的开发人员都通过客户端链接到这台服务器,获取最新的文件或者是提交更新。

这种做法的好处,就是每个人都可以在一定程度上看到项目的其他人正在做些什么。而管理员也可以轻松掌握每个开发者的权限,并且管理一个集中化的版本控制系统,要远比在客户端上维护本地数据来得轻松容易。

缺点是:中央服务器的单点故障。如果服务器宕机一小时,那么在这一小时内,谁都无法进行提交更新,也就无法协同工作。

(2)分布式版本控制工具

Git这种分布式版本控制工具,客户端提取的不是最新版本的文件快照,而是把代码仓库完整的镜像下来(本地库)。这样任何一处协同工作用的文件发生故障,事后都可以使用其他客户端的本地仓库进行恢复,因为每个客户端的每一次文件提取操作,实际上都是一次对整个文件仓库的完整备份。

分布式的版本控制系统出现以后,解决了集中式版本控制系统的缺陷:

第一:服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)

第二:每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全)

上图中缺少了一个“远程库”,代码最终会推送到远程库中

3、Git工作机制

工作区:不是开发的IDE工具,指的是你所写的代码所存放的磁盘目录的位置

暂存区:你需要让Git这个工具知道你的工作区中的代码文件,所以需要把工作区的代码文件添加到暂存区(暂存区中的代码是临时存储),这时候的代码是没有生成对应的历史版本的。暂存区中的代码是可以删除的

本地库:将暂存区的代码提交到本地库中以后,代码就有了历史版本。(本地库中的代码是无法删除的)

Git和代码托管中心

代码托管中心是基于网路服务器的远程代码仓库,我们一般称作为远程库

局域网:GitLab

互联网:GitHub(外网), Gitee码云(国内网站)

我们可以将本地库中的代码推送到远程库中

4、Git安装

Git Bash Here:右击菜单出现命令菜单

Git GUI Here:表示图形化

这里确定是否将其安装到Git目录下面,这里直接单击Next按钮

这里选择默认编辑器来对git进行编辑,这里我们默认选择Vim

以上窗口表示的是对一个新的库修改初始化分支的名字。

第一个:让Git来决定

第二个:自己进行修改

如果选择了第一个分支的名字默认是master,这里一般不需要修改,主分支一般都是master,直接单击Next按钮就可以了。

修改环境变量

第一项:只在Git Bash客户端中使用Git,选择这一项不会修改环境变量

第二项:不仅可以在Git Bash中使用Git,甚至可以在windows系统的cmd窗口中使用Git,所以这一项会修改环境变量

第三项:不选

注意: 这里我们默认选择第一项

您希望git使用哪个安全的shell客户端程序

这里我们就选第一项:使用OpenSSH进行链接

以上表示的是:选择后台客户端所链接的协议,默认选择第一项

配置行尾符号转换。

写完一行指令,需要换行。第一行与第二行之间的换行符

windows:CRLF:表示回车换行

Linux:LF

这里我们默认选择第一项,这时候Git会检查系统环境,如果是windows使用CRLF,而Linux使用LF

也就是自动转换换行符

选择客户端类型,这里默认选择第一项

如果将远程库中的代码,拉取到本地(git pull 就是获取最新的远程仓库分支到本地,并与本地分支合并),默认选择第一项。

选择一个凭证帮助程序.

如果使用git客户端拉取/推送远程库中的代码,不可能每次都登录一下,通过这个凭证帮助程序,可以记录登录的行为。

也就是第一次登录,后面就不需要登录了。

这里选择第一项:表示的是选择windows的凭证管理(第一个选项是提供登录凭证帮助的,Git 有时需要用户的凭据才能执行操作;例如,可能需要输入用户名和密码才能通过 HTTP 访问远程存储库(GitHub,GItLab 等等)。)

以上是窗口表示的是其他的配置

第一项:表示文件的缓存机制

文件系统数据将大容量读取,并缓存在内存中以进行确定操作,这将大大提高性能

第二项:启用符号链接 ,符号链接是一类特殊的文件, 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用,类似于 Windows 的快捷方式,不完全等同 类Unix(如 Linux) 下的 符号链接。因为该功能的支持需要一些条件,所以默认不开启。

配置实验选项:这是实验性功能,可能会有一些小错误之类的,建议不用开启。

最后单击Install按钮进行安装

安装成功以后,在桌面右击,在弹出的快捷菜单中,会出现Git GUI HereGit Bash Here

5、设置用户签名

git中命令比较多,常用的命令如下所示:

前两个命令是第一次使用git的时候,必须要设置用户签名,使用一次就可以了

在桌面右击,从弹出的快捷菜单中选择Git Bash Here

邮箱是可以设置一个虚拟的邮箱,也可以设置一个真实的邮箱

怎样验证用户签名设置成功了呢?

查看c盘,C:\Users(用户)\wangc(wangc表示当前电脑正在使用的用户名称,如上图所示)

找到该目录下面的.gitconfig文件,使用记事本打开查看

说明:签名的作用是区分不同的操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交者是谁。

Git首次安装必须设置一下用户签名,否则无法提交代码

注意:这里设置的用户签名和将来登录GitHub等其他代码托管中心的账号没有任何的关系。

6、初始化本地库

基本语法:git init

所谓的初始化本地库:指的就是让git这个工具管理某个目录,你需要让git获取这个目录的管理权限。

例如:E:\netcore\Git\code\demo这个目录就是项目目录,现在让git管理这个目录

在该目录中右击,在弹出的快捷菜单中选择Git Bash Here

这里执行了git init就会在当前的e/netcore/Git/code/demo目录下面创建一个空的git管理库

在该目录下面会展示一个.git目录(注意:该目录默认是隐藏的),该目录下面的文件不能修改,否则无法使用git

7、查看本地库状态

指令: git status

输出的内容

1
2
3
4
5
On branch master // 表示当前库是在master分支中

No commits yet // 表示当前没有提交任何内容

noting to commit // 没有任何需要提交的内容,因为当前项目目录中没有任何内容

下面可以直接输入vim hello.txt

使用vim编辑器创建hello.txt文件,并且可以在该文件中添加相应内容,相当于我们自己写的代码。

也可以直接在项目目录中创建hello.txt文件,然后输入内容,表示自己写的代码

这时候,可以通过cat hello.txt命令查看文件中的内容

git中的命令与linux命令是通用的。也就是可以输入linux命令

这时候再输入git status

这时候展示的前两项内容是一样的,第三项内容是不一样的,现在表示的是:未被追踪的文件,hello.txt文件名是红色的,表示该文件只是存放在工作区,还没有被git追踪到。

怎样被追踪呢?就是通过git add命令添加到暂存区就可以了。

8、添加暂存区

怎样将本地的文件添加到暂存区呢?

查看状态后,hello.txt文件名变成了绿色,表示git追踪到了这个文件,这时候hello.txt这个文件只是存储在暂存区中。

前面我们讲解过,暂存区中的文件是可以删除掉的,也就是说,不想让hello.txt这个文件保存一个历史版本。

删除的方式,就是上图中给出的git rm指令

这时候,仅仅是将hello.txt这个文件从暂存区中删除掉了。工作区中还是有该文件的。

这里可以重新执行git status查看状态。

这里我们重新执行git add hello.txt命令,将hello.txt文件重新添加到暂存区中,方便后续的测试

9、提交本地库

可以将暂存区的文件提交到本地库,从而生成历史版本

基本语法:

1
git commit -m "日志信息"  文件名

例如:

1
git commit -m "第一次提交" hello.txt

执行完以上的命令以后,查看状态

1
git status

得到的结果:

1
2
3
On branch master //  表示当前库是在master分支中
nothing to commit, working tree clean // 表示已经提交过,并且提交过以后,对应的文件没有发生变化,工作树是干净的,不需要在提交

这里缺少了No commits yet,因为现在已经提交本地库了,有自己的版本信息了,所以少了这行信息。

这里可以执行

1
git reflog

查看当前提交的引用日志信息

1
2
ada8916 (HEAD -> master) HEAD@{0}: commit (initial): 第一次提交
版本号(只展示了前七位) 当前指针指向了master分支 版本
1
git log

查询详细的日志信息

1
2
3
4
5
6
commit ada8916bab94f7181caa1c839f535b605b05d383 (HEAD -> master)  // 完整的版本号
Author: wcw <wcw@126.com> // 用户签名
Date: Tue Jun 20 10:04:12 2023 +0800

第一次提交

10、修改文件

修改hell.txt文件,表示代码修改了,看一下对应的状态

1
git status

这时候,发现文件修改以后,文件名变成了红色,表示没有被添加到暂存区。

需要再次添加到暂存区

1
git add hello.txt

再次提交到本地库

1
git commit -m "第二次提交" hello.txt

执行

1
git reflog

可以看到两个版本信息

同时,可以看到指针指向了第二个版本

如果,执行

1
cat hello.txt

查看的就是修改后的内容,也就是第二个版本的信息。

11、版本穿梭

如果想返回到以前的某个版本,可以使用版本穿梭

命令

1
git reset --hard 版本号

可以通过git reflog命令查看版本号

执行完git reset版本穿梭命令以后,可以再次执行

1
git reflog

查看到的信息如下:

1
2
3
4
ada8916 (HEAD -> master) HEAD@{0}: reset: moving to ada8916 // 这里表示了一次指针移动的操作
02c0cc6 HEAD@{1}: commit: 第二次提交
ada8916 (HEAD -> master) HEAD@{2}: commit (initial): 第一次提交 // 指针指向了第一个版本

1
cat hello.txt

查看文件中的内容,发现是第一个版本中的内容。

这里,也可以找到项目目录中的hello.txt文件,打开该文件,发现内容做了修改。

同时,可以看一下项目目录下面的.git文件夹中的HEAD文件,使用记事本打开该文件,可以看到,指针指向的就是master分支

1
ref: refs/heads/master

同时,在查看.git下面的refs文件夹中的heads文件夹中的master文件,该文件中记录的就是第一次提交的版本号。

当然,这里如果我们想再次返回到最新版本也是没有问题的。

head指针指向了master分支,然后指向了第一个版本。

如果现在又有一个新的版本,如下图所示:

12、分支概述

什么是分支

在版本控制过程中,同时推进多个任务,为每个任务我们就可以创建每个任务的单独分支。使用分支意味着开发人员可以把自己的工作从开发主线上分离开来,开发自己分支的时候,不会影响主分支的运行。对于初学者来说,分支可以简单的理解成就是副本,一个分支就是一个单独的副本。(分支底层其实也是指针的引用)

master是主分支

第一个开发人员开发了一个模块,创建了feature-blue分支,在该分支上进行开发,经过测试发现没有问题,就可以合并到master分支上,如果合并后有问题,可以在创建一个hot-fix分支进行修复,没有问题了再合并到master分支上。

第二个开发人员,开发了另外一个模块,这时候可以创建一个feature-game分支,在该分支上进行开发测试,也是经过了多个版本,发现没有问题了,最终合并到master分支上。

分支的好处:

第一:同时并行推进多个功能开发,提高开发效率

第二:各个分支在开发的过程中,如果某一个分支开发失败,不会对其他分支造成任何的影响。失败的分支删除重新开始就可以了。

13、分支的查看、创建、切换

查看分支

1
git branch -v

创建分支

1
2
3
git branch hot-fix  // 创建hot-fix分支
git branch -v // 创建完分支以后,进行查看分支

虽然现在创建了hot-fix分支,但是通过如下的提示信息,我们知道当前所在的分支还是master分支

1
2
wangc@wcw MINGW64 /e/netcore/Git/code/demo (master)

如果想切换到hot-fix这个分支,可以通过如下的命令

1
git checkout hot-fix  // 切换到hot-fix分支

切换到hot-fix这个分支以后,可以对代码文件进行修改

修改完hello.txt这个文件以后,执行git status查看状态

这时候,我们发现hello.txt这个文件名是红色的,需要提交到暂存区

执行

1
git add hello.txt

执行完以上命令以后,可以再次执行git status查看状态

下面可以提交到本地库中

1
git commit -m "hot-fix 第一次提交" hello.txt

14、合并分支

现在,我们再切换master分支

1
2
git checkout master

然后查看hello.txt文件中的内容

发现内容还是原来的内容,并没有将hot-fix分支中修改的内容合并过来。

下面,我们看一下怎样进行合并。

语法:

1
git merage 分支名

首先,当前所在的是master分支上,这样就将hot-fix分支合并到了master分支上。

合并成功以后,查看hello.txt文件中的代码

15、冲突合并

在进行代码合并的时候,可能会出现冲突的问题

导致产生冲突的原因:

合并分支的时候,两个分支在同一个文件的同一个位置有两套完全不同的修改,从而导致Git无法替我们决定使用哪一个修改。这时候必须人为决定新代码的内容

下面我们来看一下出现冲突以后,怎样进行解决

首先在master这个分支上修改hello.txt文件中的内容,如下所示:

1
2
hello git 22222
hello world master test // 添加了master test

内容修改完成以后,将其添加到暂存区

1
git add hello.txt

然后进行提交到本地库

1
2
git commit -m "master test" hello.txt

下面切换到hot-fix这个分支

1
2
git checkout hot-fix

在这个分支下面修改hello.txt文件中的内容

1
2
hello git 22222
hello world hot-fix test
1
git add hello.txt

添加到暂存区

然后进行提交

1
2
git commit -m "hot-fix test" hello.txt

提交完成以后,切换到master分支

1
git checkout master

切换到master分支以后,进行合并

1
2
git merge hot-fix

出现了如下的提示:

1
2
3
4
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt // 在hello.txt中有代码的冲突
Automatic merge failed; fix conflicts and then commit the result.// 自动合并失败

这时候在执行git status查看状态,看一下对应的提示信息

下面我们使用记事本打开hell.txt文件,该文件中的内容是:

1
2
3
4
5
6
7
hello git 22222 
<<<<<<< HEAD // 表示当前的分支
hello world master test
======= // 以上是当前分支中的代码,下面是当前合并的代码
hello world hot-fix test
>>>>>>> hot-fix

这里只能进行手动的修改,修改成如下的形式:

1
2
3
4
hello git 22222
hello world master test
hello world hot-fix test

因为这里,我们希望两个分支的内容都保存。

然后在执行

1
git add hello.txt

添加到暂存区

下面进行提交,提交到本地库中

1
git commit -m "merge hot-fix"

注意:这里没有写文件名,如果写上文件名会出现错误,也就是以下写法是错误的

1
2
git commit -m "merge hot-fix" hello.txt // 错误的写法,这里不能带上文件名

以上就是手动解决了冲突合并的问题。

16、团队协作机制

前面关于git的演示都是在本地,但是我们知道它是分布式的管理工具,这样可以进行团队协作。

如果要进行团队的协作,就需要使用到代码托管中心。

关于团队协作:分为团队内协作和跨团队协作

下面我们先来看一下团队内协作的机制,如下图所示:

A是开发经理,他搭建了一个项目的架构,放在了git的本地库中,下面他可以将本地库中的文件``push(推送)到代码托管中心中,下面开发人员B可以将代码托管中心(远程库)中的文件clone(克隆)到本地库中,也就是复制到本地库中,开发人员B就可以修改代码,修改完以后,可以再次push到代码托管中心(但是这里需要注意的一点就是,开发人员B需要具有一定的权限,也就是必须加入到当前的团队中)

项目经理A可以再次把代码托管中心中的文件pull(拉取)到本地库中。

这样开发人员A的本地库,代码托管中心,开发人员B的本地库中的代码版本都是一样的。

跨团队协作

假设团队A中的开发人员1,开发了一个项目,然后推送到远程库中了,团队B中的开发人员3,把开发人员1的项目fork(叉开)过来,然后clone到本地库中,开发人员3在本地库中进行开发,然后push推送到远程库中,这时候会向开发人员1发送一个pull request请求(拉取的请求),开发人员1,接收到请求以后,进行审核,发现没有问题了,在merge合并到开发人员1,创建的远程库中,然后在pull拉取到本地库中。

17、创建远程库

https://github.com/

进行注册登录

这里选择加号,在弹出的菜单中选择New repository

单击上图中的创建仓库的按钮以后,进入如下界面

以上地址就是远程库的地址。

这里我们先将该地址赋值到记事本中,方便后面的操作。

下面我们创建一个远程库的别名

所谓创建远程库的别名:指的就是上面的远程库地址太长了,不方便记忆,所以为了好记忆,可以为其创建一个简单的别名,方便记忆。

如下命令:

1
2
git remote add demo https://github.com/wcw324/demo.git

通过git remote add 命令来创建别名,demo就是别名,一般我们也是以本地库的名字进行命名。后面跟的就是远程库的地址。

创建好远程库以后,我们可以通过如下命令来查看创建好的别名。

1
2
git remote -v

展示的内容如下所示:

1
2
3
demo    https://github.com/wcw324/demo.git (fetch)
demo https://github.com/wcw324/demo.git (push)

展示了两个,因为可以推送,也可以拉取。

18、推送本地库到远程库

在上一小节中,我们创建好了远程库,但是远程库中没有任何的内容,这里我们可以把本地库中的文件推送到远程库中。

1
git  push 别名(远程库地址) 分支

将本地库中指定的分支推送到远程库中

例如:

1
git push demo master

将本地库中的master分支中的内容,推送到远程库中(别名是demo

一定要注意:这里你必须要明确是将本地库的哪个分支推送到远程库中。如果你想将master分支推送到远程库中,但是当前不是master分支,就需要

1
git checkout 分支名

切换到指定的分支下面

在推送的过程中,可能比较慢,因为服务器是国外的服务器。

如果一次推送不成功,多尝试几次。

在弹出以上窗口以后,可以选择以什么方式登录远程库。

这里可以选择使用浏览器,也可以选择使用账号。

当然,现在浏览器中已经打开了github,所以选择第一项就可以了。

当然,这里还需要再次进行身份的验证

刷新远程地址的页面,或者是

单击左上角的按钮,会弹出如下页面

被红色线圈起来的链接,就可以查看到所推送过来的文件内容。

19、拉取远程库到本地库

如果远程库中的代码修改了,这样就会导致你本地库与远程库中的代码不同步,这时候,可以将远程库中的代码拉取到本地(例如:团队中某个开发人员,修改了代码,你可以拉取到本地。)

这里为了方便测试,这里我们在github中,打开hello.txt文件,随意输入点内容,表示修改了代码。

单击上图中的编辑按钮,完成了信息的编辑以后,将其提交到对应的分支。

下面看一下拉取操作指令:

1
git pull 别名 分支名

当前,我们执行的拉取指令如下:

1
git pull demo master

20、克隆远程库到本地

如果你是一个新开发人员(假设就叫做张三),加入了一个新的团队,现在需要将远程库中的项目克隆到本地。

这里为了演示,我们在D盘中重新创建一个新的文件,假设叫做mydemo,作为从远程库中克隆的项目目录。

克隆的指令:

1
git clone 远程库地址

mydemo目录中,启动git 客户端,输入以下内容:

1
2
git clone https://github.com/wcw324/demo.git

在克隆的时候,不需要登录,因为我们在创建demo库的时候,创建的是公共权限(public)

克隆完成以后,在mydemo目录下面会创建一个demo文件夹,同时在demo文件夹中有.git文件夹。

所以,克隆实际上会完成如下操作

第一:拉取代码

第二:初始化本地仓库

第三:创建别名

这里我们可以看一下所创建的别名

这里我们需要先**cd demo**,有mydemo目录进入demo目录。

然后再执行

1
2
git remote -v

这时候,呈现出的结果是:

这里的别名是origin

21、团队协作

在上一小节中,张三这个开发人员从远程库中克隆了对应的项目。

下面张三就可以取修改代码或者是编写新的业务代码。

代码编写完了以后(修改了hello.txt文件中的内容),最终需要重新提交到远程库中

注意:这里是针对的mydemo目录下的demo目录进行操作。

首先先将修改的hello.txt文件添加到暂存区

然后,在通过git commit命令将其提交到本地库中。

下面就可以考虑将本地库中的代码文件提交到远程库中了。

但是,有一个问题是,张三这个开发人员,并不属于我们的团队。

所以,我们需要在GitHub这个远程库中,把张三这个账号添加到我们团队中。(当前在github上登录的是wcw324这个账号,该账号就是当前我们团队的管理员)

单击上图中的Settings这个菜单

单击左侧菜单中的Collaborators菜单,然后在右侧页面中单击Add People按钮来完成团队成员的添加。(为了做测试,在github上注册了一个新的账号)

在上面的搜索框中输入张三的账号

这里是zhangsan324

将其添加到当前wcw324这个开发人员所在的团队。

在上图中,单击红色线条圈起来的矩形框,获取对应的凭证。

把获取到的凭证以后,先拷贝到记事本中(方便后面测试)。

在公司中我们可以把上面的凭证发送给张三。

张三需要登录自己的github账号(这里单机演示的时候,需要打开另外一个浏览器进行演示,例如Edge

张三只需要在浏览器中输入发过来的凭证,敲一下回车键,会打开如下页面。

这时候,单击上图中的Accept按钮进行接受。

Decline按钮表示的婉拒

这时候,张三这个开发人员,就可以看到对应的项目了。

下面张三就可以将修改后的代码推送到对应的远程库中

在上图中,执行了

1
git push  https://github.com/wcw324/demo.git master

这样可以将张三修改的代码推送到wcw324这个开发人员所创建的远程库中。

这时候,我们可以在github中查看hello.txt文件中的内容,发现都做了响应的修改。

这时候,wcw324这个开发人员,可以将远程库中的最新代码拉取到本地,这样wcw324这个开发人员本地库中的代码就与远程库中的代码保持了一致。

在上图中执行了

1
git pull demo master

demo这个别名中拉取了最新的代码

注意:这里一定是在wcw324这个开发人员对应的git客户端拉取代码。

这样就完成了团队协作。