《Git》版本管理工具的初识与入门

前言

我所在的公司一直是使用svn作为版本管理工具,因此我没有接触过git,但是不管如何git作为目前大火的版本管理工具,了解并掌握是很有必要的,因为你不能确定下一家公司使用的是svn还是git作为版本管理;

定个小目标,静下心来好好学习git,使用新知识重构个人网站,并使用git作为版本管理工具;

简介

简单的说,就是一个版本管理工具,其作用就是管理不同的代码版本,以便如果出现问题,可以回溯,并且多人协同开发等等也是十分的方便,简而言之,就是相当好,如果你想对git的简介有更多的了解,请看廖老师的描写的部分,感觉描述的非常恰当:廖雪峰的官方网站

git和svn不同,svn是集中式的版本控制,git是分布式的版本控制,到这里就有两个关键词:集中式分布式

  • 集中式版本管理:存在一个版本库,该版本库是存放在一个中央服务器的,之后每个人都是从中央服务器更新最新的版本,然后开始码代码,等把代码码完,提交到中央服务器(PS:目前我这边就是这样,每天开始工作后,第一件事就是先使用svn将服务器上的代码更新下来,之后将代码提交到服务器)

  • 分布式版本管理:分布式版本控制没有“中央服务器”,每个人的电脑上都是一个完整的版本库,既然每个人的电脑上都有一个完整的版本库,那么如何多人协作呢?理论上你在自己的电脑上修改了文件a,同事也在电脑上修改了文件a,这是只需要将各自的修改推送给对方,这样就可以看到对方的修改了,但实际上,跟少会有两个人相互推送版本修改,还是会存在一台电脑,充当“中央服务器”的角色,这个服务器的作用仅仅是用来大家方便交换修改

安装

自行前往官网下载:Git官网下载

Mac安装:简单的就是从AppStore安装Xcode,Xcode集成了Git,Xcode是Apple官方的IDE,功能非常强大,是开发Mac和IOS的必选装备,并且免费;

Window安装:直接在官网下载安装程序,点击安装即可,安装成功之后,会有一个新的命令行工具,叫做“Git Bash”,打开会有一个类似于命令行窗口的界面,有这个就说明安装成功;

如果安装成功,在终端中输入;

git --version	//查看版本

终端工具的命令

终端工具,window里面也就是命令行工具,在工具里有一些通用的命令,比如:切换目录,显示当前目录路径等等,如果不知道这些命令,那怎么操作呢?所以先做个简单常用的记录

//显示当前路径
pwd

//切换目录
cd 路径	
//比如mac切换到用户目录下
cd /Users
//返回当前目录的上一层目录
cd ..
//返回当前电脑的用户目录
cd ~
//返回到当前电脑的根目录
cd /

//显示当前路径下所有的文件文件夹
ls
//显示所有文件,包括隐藏的
ls -la
//显示当前目录下指定文件夹内的信息
ls 文件夹名	//比如:ls test,显示当前路径下名为test的文件夹下的内容

//清除当前终端工具的界面上所有的显示
clear	//比如,你在终端操作了很多代码,界面很乱看不清了,可以使用clear代码,清除界面

//创建文件夹
mkdir 文件夹名字	//比如:mkdir test,在当前目录下创建了一个名为test的文件夹

//创建文件,文件必须包含后缀
touch 文件名字	//比如:touch 1.txt,会在当前目录下创建一个格式为txt,名字为1的文件

//删除文件
rm 文件名	//比如: rm 1.txt,会删除当前目录下名为1的txt文件,文件夹是不能直接删除的,哪怕是空的

//强制删除,删除前请确认好
rm -rf 文件名	//这种方式可以强制删除文件夹,哪怕里面有文件,所以这种删除前请务必确认

配置与查询Git

在使用Git之前需要配置用户和邮箱,为什么要配置?因为总要告诉别人是谁修改谁提交了把,不然同事怎么知道是谁修改了呢;

//配置用户
git config --global user.name "你的用户名"

回车后,没有任何提示,那么就是配置成功,如果有错误,按照提示修改后,再设置;

//配置邮箱
git config --global user.email "你的邮箱"

回车后,没有提示错误,那么就是配置成功,如果有错误,按照提示修改后,再设置;

如果忘了设置的账号邮箱,那么通过可以通过以下命令查看,该命令可以查看所有的设置信息

git config --list

如果要查看某一项配置,比如单独查看用户名,单独查看邮箱,那么可以如下

//单独查看用户名
git config user.name

//单独查看邮箱
git config user.email

如果想查看所有的命令,可以输入

//查看所有的命令提示
git help

//单独查看某个指定的命令
//比如现在通过git help查询到了一个命令叫做commit,想了解更多commit的信息,可以如下
git help commit

有时在终端会处于编辑模式,就是不是正常的输入命令的状态,那么退出编辑模式就是输入字母q就可以了

配置项目

使用git管理一个项目,首先你得拥有一个项目,之后通过cd命令,进入到该文件夹路径下,之后初始化管理项目的版本仓库

//初始化版本仓库
git init

之后会跳出一段提示,大致意思是在该路径下已经创建了一个版本仓库;这个版本仓库实际上就是一个文件夹,不过这个文件夹默认是隐藏的,因此如果是mac系统,按住:shift + command + . 这三个键可以查看隐藏文件夹,如果有git这个文件夹,那么就是初始化成功了,或者也可以通过命令查看这个文件夹,在该文件夹的路径下,输入

//显示该路径下所有隐藏和不隐藏的文件,文件夹
ls -la

假如,有一天,你不想再使用Git管理该项目了,怎么办?直接删除git这个文件夹就好了,具体可以直接删除,或者通过命令删除

项目管理

Git中一共有三中状态,已修改,已暂存,已提交,当我们修改编辑,删除,新增了文件,那么此时的文件就处于已修改状态,之后我们确认了以一下文件,似乎没问题,那么就可以通过命令,将文件添加到暂存的区域,暂存区域的这些文件就处于已暂存状态,之后,再确认这些文件ok,没有问题,可以提交到本地仓库保存了,那么再通过命令,保存到本地仓库,文件一旦保存到本地仓库,那么此时git就会生成一个时间点,在这个时间点上就会有你保存的这些文件;

查看状态

当一个项目中有新建文件,删除文件,或者修改文件后,输入以下命令查看

git status

输入命令后,在终端中对所有有修改的文件进行红色标记,换句话说,有红色标记的文件就是有修改的文件;

暂存文件

通过查看状态,发现有修改的文件,此时,就需要将有修改的文件添加入本地的版本仓库的暂存区域,可以这么理解,每一次修改,需要先将文件都放入暂存的区域,当文件在这部分区域的时候,git不会帮你记录,因为你还需要对这部分文件做进一步确认,只有确认过没有问题了,才需要确认保存到git仓库

//将指定文件添加入本地版本仓库的暂存区域
git add 具体文件名	//比如,有一个名为1.txt的文件,那么就输入 git add 1.txt

//将所有有修改的文件一次性添加到本地版本仓库的暂存区域
git add .

添加后,如果在通过git status查看文件状态,那么会发现,原本所有被标记成红色的文件,变成标记为绿色的文件,此时代表已经成功添加到暂存的区域了;

保存文件

确认文件没有问题了,并且需要将当前的文件作为一个时间节点保存,以便日后可以追踪到,那么使用命令commit提交保存到本地仓库

git commit -m "注释"

git commit代表确认将文件保存,-m则是告诉git,需要为本次提交做一个备注,为什么要备注?很简单,假设你保存了20个不同的版本,并且都没有备注,那么一旦新版本出现了问题,你怎么知道该回溯到哪个版本;

快捷提交
正常情况下,如果修改了文件,那么需要先通过git add将文件添加到暂存区,之后通过git commit 将文件保存到本地仓库,实际上还有一中更快的办法

//相当于先执行了git add . 之后执行了git commit -m "修改信息"
git commit -am "修改信息"

当然我个人觉得虽然简单了一步,但是还是按git add来的比较好,因为git add还可以再确认一次有没有问题;

移除文件

当文件处于已暂存状态时,突然发现文件里的内容有问题需要从暂存中将文件移除,不再将文件放入暂存了,那么执行

git rm --cached 文件名

如果这是发现需要将该文件删除,放入垃圾桶,这个项目不需要这个文件了,那么可以输入

git rm 文件名

如果文件已经被放到暂存了,那么如果使用上面的发现提示无法删除,那么这时候就要使用强制删除了

git rm -f 文件名

查看仓库

在多个提交之后,需要查看本地仓库有多少个记录的时候,输入

//查看本地仓库所有的版本记录
git log

之后假如本地仓库里有许多人的版本记录,那么这个时候你只需查找某一个人的,那么输入

//查找指定人员的提交记录
git log --author="用户名"

如果仅仅需要查看提交记录,那么可以输入

git log --oneline

查看仓库的版本线图

//查看git仓库上的版本线图
git log --oneline --graph

查看仓库的所有分支的版本线图

//查看git仓库上的版本线图
git log --oneline --graph --all

文件对比

正常情况下,文件修改了之后,假如需要上一次commit的版本进行对比,那么可以使用如下命令

//将当前处于已修改状态的文件和已提交的文件进行对比
git diff

这种对比,会将所有处于已修改的文件和已提交的文件进行对比,假如有3个文件修改了,那么3个文件的不同处都会标记出来;

如果,此时不小心将文件都git add过了,也就是所有的文件都被暂存了,这是git diff是不起作用的,因此需要输入

//将所有处于已暂存的文件和已提交的文件进行对比
git diff --cached

这样便可以将文件的不同处显示出来了;

文件的重命名和移动

有时候,文件的路径没有按规范存放,又或者项目的目录结构重新规整过了,需要移动文件到不同的路径下

//移动文件
git mv 原文件 文件路径
//比如
git mv Home.vue Home/	//将Home.vue文件移入Home文件夹

移动的时候,甚至可以改名,比如

//比如
git mv Home.vue Home/Home123.vue	//将Home.vue文件移入Home文件夹同时重命名为Home123.vue

利用这个远离可以为文件快速改名,比如有时候不需要移动路径,但是原模块因为功能新增,导致名字不能代表新功能模块,需要改名,那么可以

//直接改名
git mv Home.vue Home123.vue	//将Home.vue文件移入当前路径文件夹同时重命名为Home123.vue

只是利用了其移动到当前文件夹并重命名,达到了快速改名的效果;

文件的复原

还原文件到最后一次提交

很多时候修改了文件,发现修改了之后报了各种各样的错误,然后这些错误又解决不了,所以需要将文件恢复到最后一次提交的状态,需要如下操作

//将文件恢复到最后一次提交的状态
git checkout -- 文件名

//比如,现在对Home.vue进行了修改,然后报了一堆错误,又解决不了,需要直接恢复到之前保存的状态
git checkout -- src/views/Home.vue	//将src/views下的Home.vue恢复到最后一次提交时的内容

注意,如果文件此时已经处于已暂存的状态,也就是已经git add过了,那么git checkout是不会生效的,如果要对其使用git checkout,那么必须先当文件移除暂存区,也就是

//移除暂存
git rm --cached 文件名
//或者这种移除暂存,这种也是移除暂存
git reset HEAD 文件名

移出暂存区后,就可以正常使用git checkout了

版本回退

假如现在提交之后,发现存储的版本错误了,甚至在某个版本之后的所有版本都有错误,那么就需要版本回退,注意,这个回退到某一个版本之后,后面所有的版本都会消失,因此这种回溯得慎重再慎重使用

//快速回退到上个版本
git reset --hard HEAD^

//快速回退到上上个版本等等,依此类推
git reset --hard HEAD^^

如果版本很多,需要回溯到很早以前的一个版本

//回溯到很早以前的版本
git reset --hard 版本的哈希值
//比如
git reset --hard c61ebb3

后面的:c61ebb3,是指定的版本的哈希值,比如通过git log查看版本仓库之后,其中在版本之中有一个类似这个信息:commit c61ebb3031b0abd766e6830b772e3eb097c709a4;这个就是代表当前提交版本的哈希值,当然,回溯的时候不需要输入完整的哈希值,输入个前几位就可以了,比如前7位;
再次声明一下,这种回退之后不会保留回溯版本之后的所有版本,因此得慎用,如果要查看记录,那么可以

//查看回退记录
git reflog

回到旧版本

回到旧版本和版本回退有声明区别,区别就是:回到旧版本之后,在旧版本之后的版本并不会被删除,因为上一节中的版本回退,举个例子
版本回退之后
假设你的仓库里有:version 1 -> version 2 -> version 3三个版本,从version 3回到version 2之后,那么实际上version 3是会被删除的,此时你的版本库中只有:version 1 -> version 2,有时候我们不需要这样的回退,只需要将当前的版本回到某一个旧的版本;
回到旧版本之后
假设你的仓库里有:version 1 -> version 2 -> version 3三个版本,从version 3回到version 2之后,那么实际上是往当前的版本中再添加了一个版本,最后变成:version 1 -> version 2 -> version 3 -> version 2;

//单个文件恢复到旧版本
git checkout 哈希值 -- 文件名

Git分支管理

分支,Git中一个大杀器,可以这么理解,每个分支都是主线的一个备份,多个分支之间相互不影响,也就是在分支中做的开发,影响的仅仅是分支本身,不影响其他分支,也不影响marster,因此,开发的时候哪怕自己的功能只开发了一半,也可以保存到分支里面,因为你开发的不会影响到别人,只有到最终的全部开发完毕的时候,将分支合并入主线,这样你所开发的部分才会影响到每个人;

假如一个前端项目有5个人开发,一个功能往往不可能一下子就做完,很多时候需要好几天,然而我们为了保存进度,基本上每天都需要将自己做的那一部分保存,如果自己做的那部分只写了一半,然而做的这一半被别人checkout了,不说会不会影响到别人,光是这个一半是不是就是很尴尬,那么,如果有一条主线,这条主线代表了项目最终的形态,而每个人都有自己的一条支线,自己做的部分仅保存在支线里,这样就影响不到别人,一旦自己做的部分完成了,将做的合并进主线,这样合并进主线的部分才会被其他人checkout到;

主线,一半称为: master,也就是master这条线就是项目的各个阶段的最终版本;

创建分支

创建单独某个人的分支

//创建分支
git branch 分支名字
//比如,创建了一个叫做dev的分支
git branch dev

查看分支

//创建分支
git branch

切换分支

当使用git branch查看分支后,哪个分支前面有一个“*”号,那么哪个分支就是当前的分支,如果要切换

//切换分支
git checkout 分支名字
//比如切换到dev分支
git checkout dev

另外,新建分支,并且切换到新建分支,有一个快捷的合成写法

//创建一个分支并且切换到该分支下
git checkout -b 分支名字
//比如
git checkout -b dev2	//新建一个分支dev2并且切换到dev2下

删除分支

注意点是,不能在当前分支下,删除当前分支,如果要删除某个分支,必须处于其他分支下

//删除分支
git branch -d 分支名字
//比如
git branch -d dev2	//删除分支dev2

这种写法必须是dev2这个分支下没有commit的内容,如果有内容,要么先合并,要么强制删除

//强制删除
git branch -D 分支名字	//强制删除

一次性删除多个已合并的分支

//删除已合并的分支,除去当前所在的分支,除去master分支,除去develop分支
git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d

如果还有别的分支要排除,那么就按找写法加进去,或者修改

合并分支

合并

如果要合并,首先得明确谁合并到谁,通常我们是将master作为主线的,因此也就是通常将别的支线合并到master

//切换到master下
git checkout master

//将某个分支合并到master
git merge dev	//通过merge命令,将dev支线的内容合并到master下

上面说的是一种最理想的情况,一切都很顺利,但实际上,多人协同的时候,往往会出现合并的时候会发生冲突,为什么会发生冲突?原因也很简单,多人协同的时候,几个人同时创建了各自的分支,然后,其中的某个文件,a修改了,b也修改了,c也修改了,这时候a先合并进了master,等到b或者c去合并进主线的时候,文件已经不再是原来的那个文件了,如果b进行合并,那么a的内容就会被覆盖掉,因此这个时候合并就会失败,因为git不知道该这么处理了;

合并冲突解决

如果出现这种问题,该这么处理:
第一种:忽略此次合并,以master的为标准,其他分支的修改不作数,直接放弃

//忽略合并
git merge --abort

第二种:对冲突的地方逐一修改,合并后,比如master的分支里和dev的分支里有10处不同的地方,这时候git会自动帮你在文件里对这些不同的地方进行标注,然后你需要将这些标注的地方逐一修改
在这里插入图片描述
上图就是git中会给自动标注的不同的地方,这个时候,需要收到对这部分进行修改(这部分是文本,可以随便这么编辑),只留下正确的内容;
解决完所有不同的地方之后,使用命令git add .,将所有文件放入暂存,再输入命令git commit进行提交(不需要-m),提交后会出现一个类似于文本记录的页面,再这个界面上记录,具体界面如下
在这里插入图片描述
完成记录后,按键盘上的ESC键,之后输入wq,保存退出编辑模式,这样就解决了冲突

所以,发生冲突的最根本原因还是同事协同之间不沟通,相互改了都需要改的文件,因此才会出现冲突,为了避免这种问题,最好的办法还是改文件前最好相互了解一下,看看改的文件会不会也是对方需要改的文件,如果都需要改,那么及时合并一下,另外一个人在其合并的基础上checkout;

Fast forward

另外,很重要,合并分支时,Git会默认使用一个叫做Fast forward的方式进行合并,如果使用fast forward进行合并,那么分支的信息在删除分支后会丢失,如果要阻止使用Fast forward的合并方式,那么在合并时可以使用命令

//禁止使用fast forward方式合并
git merge --no-ff -m 信息 分支名 

//比如
//禁用fast forward方式合并dev分支,并进行备注
git merge --no-ff -m "merge with no-ff" dev 	

那么什么时候使用fast forward方式合并呢?居我个人查到的资料显示:

  • 如果项目是从远程仓库拉取时,比如从github(或公司中央服务器)上拉取master分支和本地master分支进行合并的时候,就需要使用fast forward方式进行合并,也就是不需要命令 --no-ff;
  • 如果是本地master分支进行合并其他分支的时候,就需要使用–no-f命令,禁止使用fast forward方式进行合并

仅合并不提交

有时候,仅仅需要合并分支,但是合并后的分支不要是已提交的状态,仅处于已暂存就够了,那么合并的时候就可以多输入一个命令–no-commit,具体如下

//合并dev分支,禁止使用fast forward方式,禁止提交
git merge --no-ff --no-commit dev

之后如果要提交,那么需要手动输入命令git commit

分支管理

实际上master分支一般不做合并,因为master分支代表的是最终的上线的稳定版,我们不可能拿稳定版去做各种开发测试,一般留给开发人员进行合并的分支叫做dev分支,在这个分支上做每个小阶段的测试,等到最终确定是稳定版本了,可以发布1.0,1.1这种大版本了,才会将dev分支上的内容合并到master分支上,所以团队合作看起来更像是如下图的分支
在这里插入图片描述

远程仓库

正常情况下,一般都有一个远程仓库,作为“中央服务器”,方便多人协同办公时的文件交换,本例中使用GitHub作为例子学习,如果公司自己建有服务器,从查到的资料来看似乎步骤差不多,大同小异;

*下面示例中的远程仓库地址以GitHub为例,请自行注册账号,新建项目;

获取远程仓库项目

//将地址上的项目拷贝下来
git clone 远程项目地址

大部分情况下,直接clone项目的时候,git会自动帮你checkout到master分支下,如果不想checkout,或者想重命名项目(如果从远程仓库clone项目时,实际上Git会自动将本地的master分支和远程的master分支对应起来,区别在于,如果没有推送权限,那么是看不到push地址的)

git clone --no-checkout 远程仓库地址 新项目名称
//比如
//下载远程地址上的项目,并且取消checkout,然后项目重命名为mywebside123
git clone --no-checkout https://github.com/xxxxx/myWebside.git mywebside123

同理如果只需要单独重命名或者不checkout都可以;

上面的这种情况只能抓去到master分支,但是master分支往往不能动,能合并操作的是dev分支,那么就需要抓去dev分支

git checkout -b dev origin/dev

上传项目到远程仓库

第一次上传的时候需要先将项目与远程地址连接起来

//通过remote连接远程仓库,这一步的作用是关联,将本地仓库和远程仓库连接起来
git remote add 自定义名字 GitHub的项目路径
//比如,连接的gitHub远程仓库
git remote add orgin https://github.com/xxxxx/myWebside.git

如果连接成功,那么输入: git remote,会显示自定义的名字,上例中对应的就是origin,之后输入以下推送到远程仓库

//将本地仓库的中的master分支推送到远程仓库
git push -u 自定义名字 master
//例如
git push -u origin master

//同理,如果需要推送的不是master,而是dev分支,那么就是
git push -u origin dev

如果想查看是否有关联远程仓库,那么输入命令

//git branch是查看本地分支,加上-r则是查看远程仓库
git branch -r
//一次性查看所有分支,包括本地,包括远程仓库
git branch -a

上面是第一次push项目到远程仓库时候时的操作,如果之后上传,仅仅只需要git push就可以了

//与远程仓库建立关系以后,只需要git push就可以上传到远程仓库了
git push

如果是推送某个指定的分支

//上传dev分支到远程仓库
git push origin dev

如果推送失败,那么就代表推送的内容和远程仓库的内容有冲突,也就是你和小伙伴修改了同一个文件,git不知道哪个是正确的,需要你手动修改;
首先先使用git pull把最新的分支抓取下来

//抓取最新的内容
git pull

//如果git pull也失败了,那么就说明本地的dev分支并没有和远程的dev分支建有联系,需要先建立联系
//之后再git pull一下
$ git branch --set-upstream-to=origin/dev dev

然后在本地合并,解决冲突,再推送
这部分详细资料还是建议看廖雪峰老师的官方网站

更新远程仓库分支

比如某个小伙伴上传了,或者直接在github里面新建了分支,此时你是看不到的,需要更新

//更新分支
git fetch

//更新后,通过git branch -a查看到了所有的新的分支,此时,哪怕本地没有这个远端分支,
//可以切换到远端分支上

//假设更新后远程仓库有一个分支new1,而本地没有
git branch new1
//此时git会自动在本地按照远程new1的设定新建一个本地分支

删除远程仓库分支

git push origin --delete 远程分支名

修改远程仓库路径

假设现在公司要求换一个仓库了,因此,原先保存的远程仓库地址不能再使用了,因此需要重新设置,那么

git remote set-url origin 新远程仓库地址

此时可以查看新地址

//查看新地址
git remote -v

已连接新仓库之后,可以通过git push提交到新仓库里去了

多人协作

实际开发中:

  • master分支是主分支,因此时刻需要与远程同步,但是,一般不会在master分支上做操作,因为master分支是代表的线上的稳定版本,瞎操作会被小伙伴打的;
  • dev分支,代表的是开发分支,团队所有成员都在上面工作,所以也要时刻与远程同步,而一般自己的功能完成后,合并的分支都是dev分支;
  • 其他分支是否需要推送,看具体情况而定;

因此,多人工作模式通常是这样的:

  • 首先,可以试图用git push origin 推送自己的修改;

  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

  • 如果合并有冲突,则解决冲突,并在本地提交;

  • 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!

  • 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。

这就是多人协作的工作模式,一旦熟悉了,就非常简单,以上内容摘自廖雪峰老师的官方网站,因为我本人也没有参与过使用git的多人协作开发,只能看个大概;

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/106781152