详解Git
版本控制
基本概念
版本控制是一个非常简单的概念,我举个例子简单说明一下你就能大概明白它是一个什么东西,当你不会版本控制的时候:
-
你的BOSS决定做一款灰常牛逼的软件,找你进行开发
-
当你做好之后,老板又突发奇想觉得加入一个新功能就更好了
-
当你添加上新功能之后,老板觉得该功能可能又不太好,让你去掉它
-
当你去掉这个功能的时候,老板说铁汁,你还是把它加上来吧,我突然觉得这个功能又挺好的
-
你心里想老板我不干了,你自己来弄吧,但是现实确让你抱起键盘乖乖就范
这个时候聪明的同学可能会这个样子做,在做完基本功能后进行拷贝,再到拷贝的副本上做出修改添加上新功能,这样不管老板怎么奇思妙想你都有应对之策:
那么这就是一个最简单的版本控制了,是不是非常简单?
历史发展
版本控制大概经历了四个阶段,如下:
- 文件夹拷贝
- 本地版本控制
- 集中式版本控制
- 分布式版本控制
文件夹拷贝
这个不必多说了,相信傻子都明白,正如上面示例中提到的对原产品进行拷贝后再添加新功能。
这个也确实是很长一段时间中的解决方案,但是它有一个非常大的问题,比如我原产品的代码有十万行,我的新功能有两万行,那么我的原产品(V1
)加上我的新功能(V2
)就要有二十二万行代码进行存储,非常的浪费存储空间(V1
十万行,V2
十二万行)。
本地版本控制
到了后面,逐渐的出现了一些软件,它可以帮助我们做版本控制,而并非由我们手动进行拷贝。
并且,它有以下几个特点:
1.同一时间只能看到一个版本,如果你想回到之前版本,就可以通过其命令等操作方式进行回滚
2.不会很干脆的进行拷贝,而是在原有代码的基础上进行增量更新,这意味着我两个版本的存储总代码量只有十四万行,非常节约空间
记住,第一个特点十分的具有代表性,那么下面放上一张Git
官网的图片,你可以清晰的看见,同一时间我们只能看到一个文件,但是在版本库中会存储多个版本:
集中式版本控制
慢慢的,大家都开始发现单兵作战不能解决全部的问题,我们需要共同生产。
所以当有多名开发者同时进行开发时,就需要有一个公共的仓库来进行存放代码,那么现在的代码都会提交至一个共有仓库中,这样一来就解决了协同开发的问题,但是相应的,如果存放共有仓库的计算机一宕机,那么大家都不能进行生产了,如果情况更加糟糕比如共有仓库中的磁盘损坏,那么大家这么久以来的辛苦就全都白费了。
这里还是举两个特征,来进行阐述:
1.集中式版本控制主要用于解决协同开发
2.所有代码都只提交至共有仓库,这样会带来一些安全隐患
分布式版本控制
为了解决集中式版本控制的弊端,后来出现了分布式版本控制,诸如 Git
、Mercurial
、Bazaar
以及 Darcs
等,你可以选择将自己写好的代码推送到本地,也可以选择推送到远程仓库。对于目前而言,这是一种非常棒的解决方案,如图所示:
你可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。
Git介绍
基本介绍
Git
是分布式的版本控制软件,以下是它的官方网站:
它的文档说明十分详细,并且使用简单,目前在大多数场景下我们都会选择Git
来做版本控制。
所以说,学习它已经是大势所趋了,逃避不了的,面对疾风吧。
下载安装
官方说明已经非常详细了,进行查看即可,里面包含了Windows
/Linux
/Mac
的安装步骤:
下面我们用Windows
做一下示例,当你下载完成后一直点击下一步即可,安装完成当在桌面右击鼠标如果出现下面两个选项,则代表安装完成。
本地仓库
由于Git
是分布式的版本控制软件,所以我们先学习如何将代码提交至本地,然后再看如何提交至远端代码库。
版本提交
在Git
中,我们首先要做的就是对一个项目进行管理。
进入项目文件夹,执行初始化命令即可由Git
接管当前项目的版本控制。
如下我们有一个mysite
的项目,在里面有一个index.html
,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>主站</title>
</head>
<body>
<h1>欢迎来到我的主站</h1>
<ul>
<li>我的喜欢</li>
<li>我的收藏</li>
<li>我的关注</li>
<li>历史记录</li>
</ul>
</body>
</html>
现在,我们需要打开terminal
,然后进入到该文件夹下,让Git
进行接管mysite
文件夹。
或者你可以直接在文件夹下单击鼠标右键,选择Git Bash Here
后在其终端中输入以下命令:
git init
当初始化命令生效后,在mysite
文件夹中会生成一个.git
的隐藏文件夹。
然后我们使用以下命令来检测当前文件夹中被管理的文件状态,输入以下命令:
git status
新增的文件和修改后的文件均属于未被管理的文件,呈现红色状态,如下所示:
接下来我们来管理该文件,有两条命令可供你选择:
git add 文件名 # 仅仅管理一个文件
git add . # 代表当前目录下的所有文件
在这里我们使用git add .
即可,当输入该命令后再次查看文件状态,会发现变成了绿色:
接下来我们开始生成第一个版本,就取名v1
吧。执行以下命令进行版本生成:
git commit -m "描述信息"
在这里它会提示一个异常,大概意思就是让你进行用户信息配置,输入用户名、邮箱等信息(只输入一次):
那么我们来配置一下个人信息,按照它提供的命令输入:
git config --global user.email "邮箱地址"
git config --global user.name "用户名"
然后再来输入git commit -m "描述信息"
提交版本,会显示提交成功。
接下来使用git log
命令查看生成的版本:
git log
好了,那么现在做一下命令小结:
命令 | 描述 |
---|---|
git init | 初始化git,让git接管当前文件夹 |
git status | 查看当前文件状态,新增或修改的文件都呈红色,而执行add命令后的文件都呈绿色 |
git add [./filename] | 将文件进行提交 |
git commit -m “描述信息” | 生成一个版本 |
git log | 查看版本提交信息 |
修改新增
当你对项目中的文件进行变动时,也会被Git
进行检测到。如下所示,我们除开index.html
外还新增了backend.html
文件。
内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>后台管理</title>
</head>
<body>
<h1>欢迎进入后台管理</h1>
</body>
</html>
现在,当我们使用git status
后,将会看到backend.html
呈红色状态。
此时我们仍然需要执行上面的步骤,来生成第二个版本。
版本回滚
如果现在你的Boss
告诉你后台功能暂时不需要,你就需要进行版本回滚,将第二版回滚到第一版。
时候如下命令进行回滚:
# 高版本回滚到低版本,先查看版本号,再设置回滚
git log
git reset --hard 版本号
现在,再次查看该项目下的文件夹,你将看不到backend.html
文件了。
同时,使用git log
命令也看不到第二版本的记录。
如果此时Boss
告诉你,后台功能挺好用的又要让你加回来,你该怎么做?因为git log
已经找不到第二版的版本号了。
别着急,你可以使用如下命令:
# 低版本回滚到高版本,使用reflog查看版本号,再设置回滚
git reflog
git reset --hard 版本号
现在,再次查看mysite
文件夹下的内容,你会发现backend.html
文件又回来了。
命令 | 描述 |
---|---|
git log | 查看版本提交信息,常用于高版本向低版本的回滚 |
git reflog | 查看版本提交信息,常用于低版本向高版本的回滚 |
git reset –hard 版本号 | 进行版本回滚 |
分区概念
在上面的操作中,可以发现目前的一个文件可以有多个状态:
- 以控制状态:指该文件可以被git管理的状态,目前来讲所有位于git init文件夹下的文件都是以控制状态
- 以变动状态:当有新文件,或原本文件被修改后,使用git status呈现红色状态的文件
- 暂存区状态:指的是执行git add命令后,红色状态文件变为绿色状态的文件
- 版本库状态:指的是执行git commit命令后,提交至版本库的文件
这些不同的状态,对应不同的分区,由于此时我们做的是本地版本控制,所以这里的版本库即为本地版本库:
使用分支
分支是Git
中非常重要的一个概念,它可以让你处理给多的突发情况,以及让你更好的进行协同开发。
多个分支互不影响,如下图所示:
不同的分支中所看到的已提交版本并不相同
当在某一分支中创建新的分支,该子分支将继承当前分支节点中的所有代码
默认有一个master分支
使用以下命令查看分支,可以看到,它默认的就有一个master
分支。
git branch
如果你想创建一个新的分支,则可以使用如下命令:
git branch 新分支名字
如下示例中,将会创建一个新的名叫dev
的分支。
图片中的*
代指你当前是处于那一条分支中,如果你想切换分支则可以使用如下命令:
git checkout 分支名字
如下实例,我们将当前分支切换进dev
:
通常情况下,一个项目最少需要两个分支,dev
与master
(默认)。
master
分支只存放一些稳定的版本。而dev
分支则存放开发版本。
现在,我想书写一个数据统计的功能,在dev
完成开发并进行提交之后,再切换至master
分支进行合并(你在那个分支下进行合并,就将代码合并到那个分支)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据统计</title>
</head>
<body>
<h1>数据统计主页</h1>
</body>
</html>
如果测试没有问题,使用如下命令进行分支合并(先切换分支):
git merge 要合并的分支
使用git log
查看提交的版本信息,你将看到有一个分支合并的提示:
对于某些分支(如测试bug),如果你不想要了,可以对其进行删除:
git branch -d 分支名称
以下是关于本小节的命令总结:
命令 | 描述 |
---|---|
git branch | 查看当前项目所有分支 |
git branch 分支名 | 创建一个新的分支 |
git checkout 分支名 | 切换分支 |
git merge 要合并的分支 | 合并分支,在那个分支下进行合并 |
git branch -d 分支名 | 删除分支 |
合并冲突
由于多分支开发,可能会出现多条分支修改同一处代码的情况,这个时候就会出现合并冲突问题。
如下所示,我们在master
中关于index.html
中的内容是这个样子的:
<h1>欢迎来到我的主站</h1>
<ul>
<li>我的喜欢</li>
<li>我的收藏</li>
<li>我的关注</li>
<li>历史记录</li>
</ul>
如果我现在在master
分支里,为index.html
添加一个新的内容,如下所示:
<h1>欢迎来到我的主站</h1>
<ul>
<li>我的喜欢</li>
<li>我的收藏</li>
<li>我的关注</li>
<li>历史记录</li>
<li>新内容(master)</li>
</ul>
并且在master
分支下对其提交到版本库中。
现在我将切换至dev
分支中,也为index.html
做修改,内容如下:
<h1>欢迎来到我的主站</h1>
<ul>
<li>我的喜欢</li>
<li>我的收藏</li>
<li>我的关注</li>
<li>历史记录</li>
<li>新内容(dev)</li>
</ul>
并且在dev
分支中提交到版本库。
现在切换回master
中进行合并,将会提示我合并冲突的问题:
如果你在vscode
等编辑器中打开index.html
,可以看到下面的画面:
合并冲突产生的原因是多条分支修改同一处代码,进行合并时Git
并不知道到底听谁的。所以索性就将其全部保留,由你来手动进行修改。
所以我把它全部删掉就解决好合并冲突了:
当然,最后进行生成最终版即可。
OK,那么关于本地仓库的介绍目前就差不多啦。看一看我们最终生成了多少个版本:
处理bug
当你master
分支即稳定版在上线部署之后出现bug
,处理流程应该是怎么样的呢?
如下图所示:
上线版本如果有bug
,应当立即创建一个新分支进行bug
修复,之后再进行提交合并。
同时这不会耽误你其他业务线的进度,当其他业务线开发完毕后,进行合并时如果没有冲突则大吉大利,如果出现冲突则解决冲突。
远程推送
GitHub
Git
是一款分布式的版本控制软件,在上面已经介绍了基本的本地版本控制。
接下来就需要介绍如何将本地版本库中的代码推送到远程版本库中,当然你可以选择的远程版本库非常多,这里就介绍GitHub
,因为它是目前使用人数最多的远程代码托管仓库。
首先你需要注册一个GitHub
,这里就不再进行演示了,自行注册即可。
创建仓库
当我们登录GitHub
之后,首先要做的就是创建一个远程仓库。
先打开仓库的页面:
然后点击New
准备新建仓库:
下面是一些设置项:
接下来你将会看到这样的页面:
OK,目前为止我们的仓库已经创建完毕咯。
推送代码
现在,尝试将mysite
中的代码推送至GitHub
吧。
输入以下两条命令:
git remote add origin https://github.com/Yunya-Github/mysite.git
git push -u origin master
由于我们是第一次使用GitHub
,所以它弹出了这样的一个页面:
我们点击中间的按钮,打开这个页面
然后点击绿色的按钮即可
你将会收到一封邮件,打开邮件后点击第一条链接,就大功告成了。
现在打开你的仓库,你就能看到文件都已经上传上去了。
值得一提的是,它只上传了master
分支,如果我们想上传dev
分支,则还是需要输入push
命令:
git push -u origin dev
现在,不管是master
还是dev
,都已经成功上传至GitHub
中了。
下面是本小结的内容梳理:
命令 | 描述 |
---|---|
git remote add 别名 仓库地址 | 给仓库地址取一个别名 |
git push -u origin 分支名 | 将分支推送至远程仓库 |
注意事项:
推送代码时,一个一个分支进行推送
拉取代码
当你在一台其他的机器上,如果想要继续进行未完成的工作,则可以将代码从远程版本库中拉下来进行书写。
如下所示,我现在在北京,但是代码却在南京,所以我想通过GitHub
继续编辑我未完成的代码。
第一步,创建文件夹:
X:\>mkdir beijing
X:\>cd beijing
X:\beijing>
第二步,使用git
拉取代码:
git clone 远程仓库地址 # 自动会取别名,名字是origin 克隆全部的代码(所有分支)
现在我们可以进行开发了,如进入dev
分支进行更新。
<h1>欢迎来到我的主站</h1>
<ul>
<li>我的喜欢</li>
<li>我的收藏</li>
<li>我的关注</li>
<li>历史记录</li>
<li>新内容(master)</li>
<li>新内容(dev)</li>
<li>在家更新的内容</li>
</ul>
在更新完成后先在dev
中进行本地提交,然后提交到GitHub
上即可。
git push origin -u dev
目前,GitHub
上的代码dev
分支也更新完毕了:
如果我回到南京后,到了原来的办公环境中,可以使用以下命令对原本的dev
进行增量更新:
git checkout dev
git pull origin dev # 增量更新
就这样循环往复即可,我画一张图感受一下:
本章节命令小结:
命令 | 描述 |
---|---|
git clone 远程仓库地址 | 克隆远程仓库所有代码(仅第一次使用) |
git pull origin 分支名 | 增量更新某一分支中的代码 |
分区概念
由于涉及到远端仓库,所以又多了一个分区:
这张图中有几个点,希望你能关注一下。
使用增量更新的pull
实际上可以拆分为两条命令:
git fetch origin 分支 # 将远程版本库的分支拉到本地版本库中
git marge origin/分支 # 将本地版本空中代码合到本地的分支中
协同开发
gitflow
gitflow
是一种工作流程,下面是在进行开发中应当遵循的一些流程。
gitflow常用分支
- Production 分支
也就是我们经常使用的Master分支,这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从其他分支合并,不能在这个分支直接修改
- Develop 分支
这个分支是我们是我们的主开发分支,包含所有要发布到下一个Release的代码,这个主要合并与其他分支,比如Feature分支
- Feature 分支
这个分支主要是用来开发一个新的功能,一旦开发完成,我们合并回Develop分支进入下一个Release
- Release分支
当你需要一个发布一个新Release的时候,我们基于Develop分支创建一个Release分支,完成Release后,我们合并到Master和Develop分支
- Hotfix分支
当我们在Production发现新的Bug时候,我们需要创建一个Hotfix, 完成Hotfix后,我们合并回Master和Develop分支,所以Hotfix的改动会进入下一个Release
初始分支
所有在Master
分支上的Commit
应该Tag
:(打标签,后面会介绍到)
Feature 分支
Feature
分支做完后,必须合并回Develop
分支, 合并完分支后一般会删点这个Feature
分支,但是我们也可以保留
Release分支
Release
分支基于Develop
分支创建,打完Release
分之后,我们可以在这个Release
分支上测试,修改Bug
等。同时,其它开发人员可以基于开发新的Feature
(记住:一旦打了Release
分支之后不要从Develop
分支上合并新的改动到Release
分支)
发布Release
分支时,合并Release
到Master
和Develop
, 同时在Master
分支上打个Tag
记住Release
版本号,然后可以删除Release
分支了。
维护分支Hotfix
hotfix
分支基于Master
分支创建,开发完后需要合并回Master
和Develop
分支,同时在Master
上打一个tag
其他事项
当然这里面有很多分支你都没接触过,没有任何关系,这只是一种工作流程,可能你的公司在用另外的流程。
单独项目
进行协同开发时,需要所有成员都能够对同一个项目进行操作,此时你需要邀请成员并且赋予其权限,否则该成员将无法开发,GitHub
上支持两种创建项目的方式供多人协同开发。
我的GitHub
上现在已经有了一个mysite
的公开项目,现在我想邀请一个开发者来进行共同开发
就这样,当他同意后,就可以与我进行协同开发。
组织项目
公司常常采用组织的形式来进行协同开发,一个组织下可以有多个项目,那么我们现在来创建一个组织。
现在,你可以将你的第一个版本提交至该仓库中。
tag应用
我们上面看得到的版本号,都是一大串哈希值。
这显然十分的不友好,所以在开发时最好能够给每个版本打一个别名,或者称之为标签。
现在我们新创建了一个本地项目叫NBSite
,并且写好了初版。在提交时我们需要给他打上一个标签。
git tag -a v1.0 -m "描述" # 在本地创建tag信息
git tag -d v1.0 # 删除tag
git push origin --tags # 将本地tag信息推送到远程仓库
git pull origin --tags # 更新本地tag版本信息
git checkout v.10 # 切换tag
git clone -b v-.1 地址 # 指定tag下载代码
现在,我们的远程仓库上,已经对初始版有了个tag了,以后更新版本,切记打上标签。
邀请开发
首先邀请我们的好朋友登场:
现在,我们亲爱的KAEJKING
经过邮件确认后已经进入组织了,点击NBSite
这个项目,赋予KAEJKING
权限。
开始工作
现在KAEJKING
这个成员已经有写的权限了。我们尝试让它对NBSite
项目做出更新。
git clone https://github.com/KAKOFS/NBSite.git
cd NBSite
git checkout dev # 切换到dev
git bransh KAEJKING # 创建新的分支,可以以功能命名,也可以人名。一定要在dev下创建
# 写代码
git add .
git commit -m "KAEJKING开发的新功能"
git push origin KAEJKING # 将开发的分支推送到组织仓库
代码review
review
是一个新的基于dev
的分支,由于KAEJKING
是基于dev
的功能分支。所以合并前我们要进行代码测试,也就是review
完成后才能够将KAEJKING
开发的内容合并到dev
分支。
现在,管理员已经收到了合并请求。进行审查之后代码没有问题就可以直接合并到dev
分支了。
review
完成之后,KAEJKING
写的新功能将会合并到dev
分支中。
代码release
现在dev
分支已经做了更新,如果想更新到master
分支中,还需要进行代码release
,这是一次十分严格的测试,所以应该由一个测试团队来进行。
-
基于
dev
分支创建release
分支git checkout dev git checkout -b relase
-
进行测试
-
测试完成,将
relase
的代码合并到master
分支git merge relase # master分支下做
-
在
master
分支打tag
,进行代码上传。git tag -a v2 -m "正式版第二版上线" git push origin --tags
-
运维人员可以下载代码做上线了
git clone -b v2 地址
其他操作
rebase命令
当你每天都进行代码提交,那么你的提交记录将会变得非常的繁琐。如下所示:
print("初始版本")
print("我第一天写了这么多代码了") # 生成版本 第一天
print("我第二天写了这么多代码了") # 生成版本 第二天
print("我第三天写了这么多代码了") # 生成版本 第三天
print("终于开发完毕了") # 生成版本 最终版
其实,你的Boss
并不关心你第几天开发了多少多少,它只关心最终版。
所以我们需要把中间三天进行合并,让他看起来更简洁。(这可能会引发合并冲突)
使用如下命令进行合并:
git rebase -i HEAD~4 # 从最上面的版本数四个进行合并
现在它会弹出一个vim
,让你编辑描述信息。
我对他稍作修改。
再使用git log
进行查看,就简洁多了:
注意,它其实是将当前分支中的多个版本进行融合成一个版本,
所以可能导致合并冲突。
配置文件
git
中的配置文件有三部分。
- 仓库级的配置文件:在仓库的
.git/.gitconfig
,该配置文件只对所在的仓库有效。 - 全局配置文件:
Mac
系统在~/.gitconfig
,Windows
系统在C:\Users\<用户名>\.gitconfig
。 - 系统级的配置文件:在
Git
的安装目录(Mac
系统下安装目录在/usr/local/git
)的etc
文件夹中的gitconfig
。
-
当前项目的配置文件
git config --local user.name "xxx" git config --local user.email "xxx@xx.com"
-
全局配置文件
git config --global user.name "xxx" git config --global user.email "xxx@xx.com"
-
系统配置文件
git config --system user.name "xxx" git config --system user.email "xxx@xx.com" # 需要有root权限
SSH
使用SSH
也可以实现代码的推送和拉取。
~
代表当前目录。
-
生成公钥与私钥(默认放在~/.ssh目录下,id_rsa.pub为公钥,id_rsa为私钥)
ssh-keygen # 一直回车,生成密钥
-
拷贝公钥的内容,设置到
GitHub
中 -
在
Git
本地配置SSH
地址git remote add origin git@github.com:KAKOFS/NBSite.git # ssh地址
-
使用时用以下命令
git push origin 分支名
fork源码
如果你想对一些框架的源码做出贡献,可以使用以下步骤向框架开发者提出合并请求。
-
fork
源代码,将别人源码拷贝到我自己的远程仓库。 -
在自己仓库中进行修改代码
-
给源代码作者提交修复
bug
申请。(pull request
)
忽略文件
在项目中创建.gitignore
文件,输入匹配规则,当前项目中所有匹配的文件将不会被Git
所管理。
你还可以有更多的匹配规则:
*.h # 忽略.h的后缀文件
!a.h # 但是不忽略a.h这个文件
files/ # 忽略该文件夹下所有文件
*.py[a|b|c] # 忽略pya、pyb、pyc为后缀的文件
issues&wiki
issues
可以提出一些你发现的问题,开发者会给你进行解答。
使用wiki
来对你的项目进行描述,以方便你走后接替你工作的人更快的熟悉该项目。
删除不存在的分支
多人合作开发时,如果远程的分支被其他开发删除掉,在本地执行 git branch --all
依然会显示该远程分支,可使用下列的命令进行删除:
# 使用 pull 命令,添加 -p 参数
$ git pull -p
# 等同于下面的命令
$ git fetch -p
$ git fetch --prune origin
命令大全
本篇命令
下面是一些在本文章中有的命令:
命令 | 描述 |
---|---|
git init | 初始化 |
git status | 查看状态 |
git add | 管理指定文件 |
git commit -m “描述” | 生成版本 |
git log | 查看版本记录(之前) |
git reflog | 查看版本记录(之后) |
git reset –hard 版本号 | 版本回滚 |
git branch | 查看所有分支 |
git branch 分支名 | 创建新分支 |
git checkout 分支名 | 切换分支 |
git merge | 分支合并 |
git branch -d 分支名 | 删除分支 |
git remote add 别名 地址 | 远程仓库取别名 |
git push -u 别名 分支 | 推送某分支到远程仓库 |
git clone 地址 | 克隆远程仓库代码 |
git pull 别名 分支 | 拉取远程仓库中某一分支代码,增量更新 |
git rebase -i HEAD~条数 | 版本合并 |
config
配置的相关命令及参数:
# 查看配置信息
# --local:仓库级,--global:全局级,--system:系统级
$ git config <--local | --global | --system> -l
# 查看当前生效的配置信息
$ git config -l
# 编辑配置文件
# --local:仓库级,--global:全局级,--system:系统级
$ git config <--local | --global | --system> -e
# 添加配置项
# --local:仓库级,--global:全局级,--system:系统级
$ git config <--local | --global | --system> --add <name> <value>
# 获取配置项
$ git config <--local | --global | --system> --get <name>
# 删除配置项
$ git config <--local | --global | --system> --unset <name>
# 配置提交记录中的用户信息
$ git config --global user.name <用户名>
$ git config --global user.email <邮箱地址>
# 更改Git缓存区的大小
# 如果提交的内容较大,默认缓存较小,提交会失败
# 缓存大小单位:B,例如:524288000(500MB)
$ git config --global http.postBuffer <缓存大小>
# 调用 git status/git diff 命令时以高亮或彩色方式显示改动状态
$ git config --global color.ui true
# 配置可以缓存密码,默认缓存时间15分钟
$ git config --global credential.helper cache
# 配置密码的缓存时间
# 缓存时间单位:秒
$ git config --global credential.helper 'cache --timeout=<缓存时间>'
# 配置长期存储密码
$ git config --global credential.helper store
git clone
从远程仓库克隆一个版本库到本地。
# 默认在当前目录下创建和版本库名相同的文件夹并下载版本到该文件夹下
$ git clone <远程仓库的网址>
# 指定本地仓库的目录
$ git clone <远程仓库的网址> <本地目录>
# -b 指定要克隆的分支,默认是master分支
$ git clone <远程仓库的网址> -b <分支名称> <本地目录>
git init
初始化项目所在目录,初始化后会在当前目录下出现一个名为 .git
的目录。
# 初始化本地仓库,在当前目录下生成 .git 文件夹
$ git init
git status
查看本地仓库的状态。
# 查看本地仓库的状态
$ git status
# 以简短模式查看本地仓库的状态
# 会显示两列,第一列是文件的状态,第二列是对应的文件
# 文件状态:A 新增,M 修改,D 删除,?? 未添加到Git中
$ git status -s
git remote
操作远程库。
# 列出已经存在的远程仓库
$ git remote
# 列出远程仓库的详细信息,在别名后面列出URL地址
$ git remote -v
$ git remote --verbose
# 添加远程仓库
$ git remote add <远程仓库的别名> <远程仓库的URL地址>
# 修改远程仓库的别名
$ git remote rename <原远程仓库的别名> <新的别名>
# 删除指定名称的远程仓库
$ git remote remove <远程仓库的别名>
# 修改远程仓库的 URL 地址
$ git remote set-url <远程仓库的别名> <新的远程仓库URL地址>
git branch
操作 Git 的分支命令.
# 列出本地的所有分支,当前所在分支以 "*" 标出
$ git branch
# 列出本地的所有分支并显示最后一次提交,当前所在分支以 "*" 标出
$ git branch -v
# 创建新分支,新的分支基于上一次提交建立
$ git branch <分支名>
# 修改分支名称
# 如果不指定原分支名称则为当前所在分支
$ git branch -m [<原分支名称>] <新的分支名称>
# 强制修改分支名称
$ git branch -M [<原分支名称>] <新的分支名称>
# 删除指定的本地分支
$ git branch -d <分支名称>
# 强制删除指定的本地分支
$ git branch -D <分支名称>
git checkout
检出命令,用于创建、切换分支等。
# 切换到已存在的指定分支
$ git checkout <分支名称>
# 创建并切换到指定的分支,保留所有的提交记录
# 等同于 "git branch" 和 "git checkout" 两个命令合并
$ git checkout -b <分支名称>
# 创建并切换到指定的分支,删除所有的提交记录
$ git checkout --orphan <分支名称>
# 替换掉本地的改动,新增的文件和已经添加到暂存区的内容不受影响
$ git checkout <文件路径>
git cherry-pick
把已经提交的记录合并到当前分支。
# 把已经提交的记录合并到当前分支
$ git cherry-pick <commit ID>
git add
把要提交的文件的信息添加到暂存区中。当使用 git commit
时,将依据暂存区中的内容来进行文件的提交。
# 把指定的文件添加到暂存区中
$ git add <文件路径>
# 添加所有修改、已删除的文件到暂存区中
$ git add -u [<文件路径>]
$ git add --update [<文件路径>]
# 添加所有修改、已删除、新增的文件到暂存区中,省略 <文件路径> 即为当前目录
$ git add -A [<文件路径>]
$ git add --all [<文件路径>]
# 查看所有修改、已删除但没有提交的文件,进入一个子命令系统
$ git add -i [<文件路径>]
$ git add --interactive [<文件路径>]
git commit
将暂存区中的文件提交到本地仓库中。
# 把暂存区中的文件提交到本地仓库,调用文本编辑器输入该次提交的描述信息
$ git commit
# 把暂存区中的文件提交到本地仓库中并添加描述信息
$ git commit -m "<提交的描述信息>"
# 把所有修改、已删除的文件提交到本地仓库中
# 不包括未被版本库跟踪的文件,等同于先调用了 "git add -u"
$ git commit -a -m "<提交的描述信息>"
# 修改上次提交的描述信息
$ git commit --amend
git fetch
从远程仓库获取最新的版本到本地的 tmp 分支上。
# 将远程仓库所有分支的最新版本全部取回到本地
$ git fetch <远程仓库的别名>
# 将远程仓库指定分支的最新版本取回到本地
$ git fetch <远程主机名> <分支名>
git merge
合并分支。
# 把指定的分支合并到当前所在的分支下
$ git merge <分支名称>
git diff
比较版本之间的差异。
# 比较当前文件和暂存区中文件的差异,显示没有暂存起来的更改
$ git diff
# 比较暂存区中的文件和上次提交时的差异
$ git diff --cached
$ git diff --staged
# 比较当前文件和上次提交时的差异
$ git diff HEAD
# 查看从指定的版本之后改动的内容
$ git diff <commit ID>
# 比较两个分支之间的差异
$ git diff <分支名称> <分支名称>
# 查看两个分支分开后各自的改动内容
$ git diff <分支名称>...<分支名称>
git pull
从远程仓库获取最新版本并合并到本地。
首先会执行 git fetch
,然后执行 git merge
,把获取的分支的 HEAD 合并到当前分支。
# 从远程仓库获取最新版本。
$ git pull
git push
把本地仓库的提交推送到远程仓库。
# 把本地仓库的分支推送到远程仓库的指定分支
$ git push <远程仓库的别名> <本地分支名>:<远程分支名>
# 删除指定的远程仓库的分支
$ git push <远程仓库的别名> :<远程分支名>
$ git push <远程仓库的别名> --delete <远程分支名>
git log
显示提交的记录。
# 打印所有的提交记录
$ git log
# 打印从第一次提交到指定的提交的记录
$ git log <commit ID>
# 打印指定数量的最新提交的记录
$ git log -<指定的数量>
git reset
还原提交记录。
# 重置暂存区,但文件不受影响
# 相当于将用 "git add" 命令更新到暂存区的内容撤出暂存区,可以指定文件
# 没有指定 commit ID 则默认为当前 HEAD
$ git reset [<文件路径>]
$ git reset --mixed [<文件路径>]
# 将 HEAD 的指向改变,撤销到指定的提交记录,文件未修改
$ git reset <commit ID>
$ git reset --mixed <commit ID>
# 将 HEAD 的指向改变,撤销到指定的提交记录,文件未修改
# 相当于调用 "git reset --mixed" 命令后又做了一次 "git add"
$ git reset --soft <commit ID>
# 将 HEAD 的指向改变,撤销到指定的提交记录,文件也修改了
$ git reset --hard <commit ID>
git revert
生成一个新的提交来撤销某次提交,此次提交之前的所有提交都会被保留。
# 生成一个新的提交来撤销某次提交
$ git revert <commit ID>
git tag
操作标签的命令。
# 打印所有的标签
$ git tag
# 添加轻量标签,指向提交对象的引用,可以指定之前的提交记录
$ git tag <标签名称> [<commit ID>]
# 添加带有描述信息的附注标签,可以指定之前的提交记录
$ git tag -a <标签名称> -m <标签描述信息> [<commit ID>]
# 切换到指定的标签
$ git checkout <标签名称>
# 查看标签的信息
$ git show <标签名称>
# 删除指定的标签
$ git tag -d <标签名称>
# 将指定的标签提交到远程仓库
$ git push <远程仓库的别名> <标签名称>
# 将本地所有的标签全部提交到远程仓库
$ git push <远程仓库的别名> –tags
git mv
重命名文件或者文件夹。
# 重命名指定的文件或者文件夹
$ git mv <源文件/文件夹> <目标文件/文件夹>
git rm
删除文件或者文件夹。
# 移除跟踪指定的文件,并从本地仓库的文件夹中删除
$ git rm <文件路径>
# 移除跟踪指定的文件夹,并从本地仓库的文件夹中删除
$ git rm -r <文件夹路径>
# 移除跟踪指定的文件,在本地仓库的文件夹中保留该文件
$ git rm --cached