【Git企业级教学,原来拉代码如此简单?】


1 🍑环境准备🍑

centos平台上,我们可以使用git命令来查看是否安装了git:

[grm@iZ2vcf5z5ky8svdkf00zfzZ home]$ git
bash: git: command not found

如果显示了上面结果,那就说明没有安装git,此时我们可以使用以下命令安装:
sudo yum -y install git
使用git --version命令可以查看 Git 安装的版本。


2 🍑git 的基本操作🍑

2.1 🍎创建 git 本地仓库🍎

要提前说的是,仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来。创建⼀个 Git 本地仓库对应的命令为git init,注意命令要在⽂件⽬录下执⾏。
比如下面我们创建了一个gitcode的目录,并且在里面执行git init命令:
在这里插入图片描述查看该目录:
在这里插入图片描述

我们发现,当前⽬录下多了⼀个 .git 的隐藏目录, .git 目录是 Git 来跟踪管理仓库的,记住不要⼿动修改这个⽬录⾥⾯的东西,不然改乱了,就把 Git 仓库给破坏了。

我们先查看 .git目录下的所有文件,这里只是简单看一下,后面我们会对每一个部分做出解释:
在这里插入图片描述

2.2 🍎配置 git🍎

当安装 Git 后⾸先要做的事情是设置你的 用户名称e-mail 地址,配置命令为:

git config [--global] user.name "Your Name" 
git config [--global] user.email "email@example.com" 
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可

其中 --global 是⼀个可选项。如果使⽤了该选项,表⽰这台机器上所有的 Git 仓库都会使⽤这个配置。如果你希望在不同仓库中使⽤不同的 name 或 e-mail ,可以不要 --global 选项,但要注意的是,执⾏命令时必须要在仓库⾥。查看配置命令为:git config -l

在这里插入图片描述删除对应的配置命令为:

git config [--global] --unset user.name
git config [--global] --unset user.email

2.3 🍎认识工作区、暂存区、版本库🍎

  • 工作区:是在电脑上你要写代码或⽂件的⽬录。
  • 暂存区:英⽂叫 stage 或 index。⼀般存放在.git⽬录下的 index ⽂件(.git/index)中,我们把暂存区有时也叫作索引(index)。
  • 版本库:⼜名仓库,英⽂名 repository 。⼯作区有⼀个隐藏⽬录.git,它不算⼯作区,⽽是 git 的版本库。这个版本库⾥⾯的所有⽂件都可以被 Git 管理起来,每个⽂件的修改、删除,git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

下⾯这个图展⽰了⼯作区、暂存区和版本库之间的关系:
在这里插入图片描述图中左侧为⼯作区,右侧为版本库。Git 的版本库⾥存了很多东西,其中最重要的就是暂存区。

  • 在创建 Git 版本库时,Git 会为我们⾃动创建⼀个唯⼀的 master 分⽀,以及指向 master 的⼀个指针叫HEAD;
  • 当对⼯作区修改(或新增)的⽂件执⾏git add命令时,暂存区⽬录树的⽂件索引会被更新;
  • 当执⾏提交操作git commit时,master 分⽀会做相应的更新,可以简单理解为暂存区的⽬录树才会被真正写到版本库中.

由上述描述我们便能得知:通过新建或粘贴进⽬录的⽂件,并不能称之为向仓库中新增⽂件,⽽只是在⼯作区新增了⽂件。必须要通过使⽤git addgit commit命令才能将⽂件添加到仓库中进⾏管理。

2.4 🍎git add 和 git commit 的基本使用🍎

我们在与 .git 目录同级目录下创建一个文件Upload,使⽤git add命令可以将⽂件添加到暂存区:

  • 添加⼀个或多个⽂件到暂存区: git add [file1] [file2] …
  • 添加指定⽬录到暂存区,包括⼦⽬录: git add [dir]
  • 添加当前⽬录下的所有⽂件改动到暂存区: git add .

注意:不仅仅可以添加文件,目录也是OK的。

在这里插入图片描述
此时我们就在暂存区中添加了一个Upload文件。

再使⽤git commit命令将暂存区内容添加到本地仓库中:

  • 提交暂存区全部内容到本地仓库中: git commit -m “message”
  • 提交暂存区的指定⽂件到仓库区: git commit [file1] [file2] … -m “message”

注意git commit后⾯的-m选项,后面要跟上描述本次提交的 message,由用户⾃⼰完成,这部分内容绝对不能省略,并要好好描述,是⽤来记录你的提交细节,比如我们修改了一个什么Bug,添加了一些功能等。

在这里插入图片描述
此时我们可以使用git log命令来查看提交的日志消息:

在这里插入图片描述最开始Upload文件中是没有数据的,此时我们在Upload文件添加一行数据并保存,然后使用git addgit commit命令:
在这里插入图片描述此时我们可以看见,git是能够告诉用户增加了数据还是删减了数据。

我们还可以多次add不同的⽂件,⽽只commit⼀次便可以提交所有⽂件,是因为需要提交的⽂件是通通被add到暂存区中,然后⼀次性commit暂存区中的所有修改。

查看日志信息时有时候可能输出的消息太多,不便于观察,可以加上 --pretty=oneline选项:
在这里插入图片描述需要说明的是,我们看到的⼀⼤串类似20bd……08的是每次提交的 commit id (版本号),Git 的 commit id 不是1,2,3……递增的数字,⽽是⼀个 SHA1 计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰。

此时我们查看.log目录下的文件,会发现多出了一些东西:
在这里插入图片描述

  • 1️⃣ index就是我们的暂存区, add 后的内容都是添加到这⾥的;

  • 2️⃣HEAD 就是我们的默认指向 master 分⽀的指针;
    在这里插入图片描述

默认的 master 分⽀又是什么鬼呢?
在这里插入图片描述
打印的 20bd60bc38abd76737b112fc87e5cf7f3cdc6f08 是什么东西呢?保存的就是当前最新的 commit id。

  • 3️⃣objects 为 Git 的对象库,⾥⾯包含了创建的各种版本库对象及内容。当执⾏git add命令时,暂存区的⽬录树被更新,同时⼯作区修改(或新增)的⽂件内容被写⼊到对象库中的⼀个新的对象中,就位于 .git/objects ⽬录下,让我们来看看这些对象有何⽤处:
    在这里插入图片描述
    查找 object 时要将 commit id 分成2部分,其前2位是⽂件夹名称,后38位是⽂件名称。
    找到这个⽂件之后,⼀般不能直接看到⾥⾯是什么,该类⽂件是经过 sha (安全哈希算法)加密过的⽂件,不过我们可以使⽤git cat-file命令来查看版本库对象的内容:

在这里插入图片描述
总结⼀下,在本地的 git 仓库中,有⼏个⽂件或者⽬录很特殊:

  • index: 暂存区, git add 后会更新该内容。
  • HEAD: 默认指向 master 分⽀的⼀个指针。
  • refs/heads/master: ⽂件⾥保存当前 master 分⽀的最新 commit id 。
  • objects: 包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。

2.5 🍎修改文件🍎

Git ⽐其他版本控制系统设计得优秀,因为 Git 跟踪并管理的是修改,⽽⾮⽂件。
什么是修改?⽐如你新增了⼀⾏,这就是⼀个修改,删除了⼀⾏,也是⼀个修改,更改了某些字符,也是⼀个修改,删了⼀些⼜加了⼀些,也是⼀个修改,甚⾄创建⼀个新⽂件,也算⼀个修改。

此时修改下Upload文件中的数据:
在这里插入图片描述

但是过了一段时间后我们忘记了怎么办?此时可以使用git status 命令⽤于查看在你上次提交之后是否有对⽂件进⾏再次修改:
在这里插入图片描述上⾯的结果告诉我们,Upload 被修改过了,但还没有完成添加与提交。

⽬前,我们只知道⽂件被修改了,如果能知道具体哪些地⽅被修改了,就更好了。此时可以使用git diff命令显⽰暂存区和⼯作区⽂件的差异,也可以使⽤git diff HEAD -- [file]命令来查看版本库和⼯作区⽂件的区别。
在这里插入图片描述
add之后:
在这里插入图片描述
就看不见最后一行no changes added to commit (use "git add" and/or "git commit -a")

2.6 🍎版本回退🍎

之前我们也提到过,Git 能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现之前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。

执⾏git reset命令⽤于回退版本,可以指定退回某⼀次提交的版本。要解释⼀下“回退”本质是要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定。
git reset 命令语法格式为:

git reset [--soft | --mixed | --hard] [HEAD]
  • --mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内容,⼯作区⽂件保持不变。

  • --soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。

  • --hard 参数将暂存区与⼯作区与版本库都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。

  • HEAD 说明:
    可直接写成 commit id,表⽰指定退回的版本:

    • HEAD 表⽰当前版本
    • HEAD^ 上⼀个版本
    • HEAD^^ 上上⼀个版本

    也可以使⽤~数字表⽰:

    • HEAD~0 表⽰当前版本
    • HEAD~1 上⼀个版本
    • HEAD~2 上上⼀个版本

我们先来做一下准备工作,首先提交3个版本的内容,然后使用git log命令进行查看:
在这里插入图片描述

现在,如果我们在提交完 version3 后, 发现 version 3 编写错误,想回退到 version1,重新基于version 1 开始编写。由于我们在这⾥希望的是将⼯作区的内容也回退到 version 2 版本,所以需要⽤到--hard参数,⽰例如下:

在这里插入图片描述但现在如果我后悔了,想再回到 version 3 怎么办?我们可以继续使⽤git reset命令,回退到 version 3 版本,但我们必须要拿到 version 3 的 commit id 去指定回退的版本。我们可以查看之前的id来进行回退:
在这里插入图片描述那假如我们在终端上已经找不到之前敲的命令了应该咋办呢?我们可以使用 git reflog 命令补救⼀下,该命令⽤来记录本地的每⼀次命令。
在这里插入图片描述大家注意到了没前面这一行数据没,我们还可以使用前面这一行数据id对应的版本来进行回退,比如现在我想要回退到版本2,此时我们可以这样回退:
在这里插入图片描述

Git 的版本回退速度⾮常快,因为 Git 在内部有个指向当前分⽀(此处是master)的HEAD 指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version。

2.7 🍎撤销修改🍎

如果我们在我们的⼯作区写了很⻓时间代码,越写越写不下去,觉得⾃⼰写的实在是垃圾,想恢复到上⼀个版本。

情况⼀:对于⼯作区的代码,还没有 add

大家想到的最简便的方法是直接删除修改的代码就行了,但是问题是万一我们修改量很大,记不住了怎么办?所以我们可以使用Git 提供的⽅式,git checkout -- [file]命令让⼯作区的⽂件回到最近⼀次 add 或 commit 时的状态。 要注意该命令中的 -- 很重要,切记不要省略,⼀旦省略,该命令就变为其他意思了,后⾯我们再说。

我们简单验证一下:
在这里插入图片描述

情况⼆:已经 add ,但没有 commit

add 后还是保存到了暂存区中,怎么撤销呢?

让我们来回忆⼀下学过的git reset回退命令,该命令如果使⽤--mixed参数,可以将暂存区的内容退回为指定的版本内容,但⼯作区⽂件保持不变。那我们就可以回退下暂存区的内容了!
在这里插入图片描述
此时⽤git status查看⼀下,发现暂存区是⼲净的,⼯作区有修改:
在这里插入图片描述

情况三:已经 add ,并且也 commit 了

我们可以git reset --hard HEAD^回退到上⼀个版本!不过,这是有条件的,就是你还没有把⾃⼰的本地版本库推送到远程。

2.8 🍎删除文件🍎

首先准备好一个测试文件file1,向里面写入数据并且add和commit:
在这里插入图片描述
此时我们能够直接使用rm删除文件吗?我们可以试试,删除完毕后我们使用git status命令进行查看:
在这里插入图片描述
从上面我们可以看出我们只是删除了文件,但是现在版本库中仍然存在。假如误删了我们可以使用git checkout命令补救:
在这里插入图片描述
那假如我们想要将⽂件从暂存区和⼯作区中删除呢?我们可以使用git rm命令,然后将删除的结果使用commit进行提交即可:
在这里插入图片描述
在这里插入图片描述


3 🍑分⽀管理🍑

3.1 🍎理解分支🍎

在版本回退⾥,你已经知道,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。截⽌到⽬前,只有⼀条时间线,在Git⾥,这个分⽀叫主分⽀,即 master 分⽀。

再来理解⼀下HEAD,HEAD 严格来说不是指向提交,⽽是指向master,master才是指向提交的,所以,HEAD 指向的就是当前工作分⽀。

在这里插入图片描述
每次提交,master分⽀都会向前移动⼀步,这样随着你不断提交,master分⽀的线也越来越⻓,⽽HEAD只要⼀直指向master分⽀即可指向当前分⽀。

3.2 🍎创建分⽀🍎

Git ⽀持我们查看或创建其他分⽀,在这⾥我们来创建第⼀个⾃⼰的分⽀ dev ,对应的命令为 git branch
我们可以先使用git branch 查看当前所有分支:
在这里插入图片描述

其中有*的表示当前的工作分支。下面我们再创建一个dev分支:
在这里插入图片描述
此时我们查看.git的目录结构时会发现多出了一个dev分支:
在这里插入图片描述
在这里插入图片描述
发现⽬前 dev 和 master 指向同⼀个修改。
在这里插入图片描述

3.3 🍎切换分支🍎

使⽤git checkout命令即可完成切换,⽰例如下:
在这里插入图片描述
在这里插入图片描述
我们发现 HEAD 已经指向了 dev,就表⽰我们已经成功的切换到了 dev 上。

接下来,在 dev 分⽀下修改 Upload ⽂件,新增⼀⾏内容,并进⾏⼀次提交操作:

在这里插入图片描述
此时我们切回到master,查看工作区中的内容:
在这里插入图片描述
我们此时发现居然这里面没有我们刚才在dev中修改的数据,赶紧再切回 dev 看看:
在这里插入图片描述
发现此时数据又有了,为什么会出现这个现象呢?我们来看看 dev 分⽀和 master 分⽀指向,发现两者指向的提交是不⼀样的:
在这里插入图片描述
看到这⾥就能明⽩了,因为我们是在dev分⽀上提交的,⽽master分⽀此刻的提交点并没有变,此时的状态如图如下所⽰:
在这里插入图片描述
此时dev是最新提交的,而master则是上一次提交的。当切换到 master 分⽀之时,HEAD 就指向了 master,当然看不到最新提交了。

3.4 🍎合并分⽀🍎

为了在 master 主分⽀上能看到新的提交,就需要将dev分⽀合并到master分⽀,⽰例如下:
我们先切换到master分支,然后进行合并:
在这里插入图片描述
此时我们就在master下看见了最新提交:
在这里插入图片描述
我们在合并时会出现Fast-forward,Fast-forward 代表“快进模式”,也就是直接把master指向dev的当前提交:
在这里插入图片描述

3.5 🍎删除分⽀🍎

合并完成后, dev 分⽀对于我们来说就没⽤了, 那么dev分⽀就可以被删除掉,注意如果当前正处于某分⽀下,就不能删除当前分⽀,如:
在这里插入图片描述也就是自己不能够删除自己。另外要注意git branch -d命令适用于已经合并了的分支进行删除,对于没有进行合并的分支后面我们会讲解删除方式。
在这里插入图片描述
此时的状态如图如下所⽰:
在这里插入图片描述
因为创建、合并和删除分⽀⾮常快,所以Git⿎励你使⽤分⽀完成某个任务,合并后再删掉分⽀,这和直接在master分⽀上⼯作效果是⼀样的,但过程更安全。

我们使用下面命令来查看提交日志不难发现:
在这里插入图片描述
此时我们使用Fast-forward模式是无法区分是合并提交的?还是只在master上提交?

3.6 🍎合并冲突🍎

可是,在实际分⽀合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。
为了演⽰这问题,创建⼀个新的分⽀ dev1 ,并切换⾄⽬标分⽀,我们可以使⽤git checkout -b dev1⼀步完成创建并切换的动作,⽰例如下:
在这里插入图片描述
先看看原始文件中的数据:
在这里插入图片描述
在 dev1 分⽀下修改 Upload ⽂件,更改⽂件内容如下,并进⾏⼀次提交,如:
在这里插入图片描述
切换⾄ master 分⽀,观察 Upload ⽂件内容:
在这里插入图片描述
我们发现,切回来之后,⽂件内容由变成了⽼的版本,这种现象很正常,我们现在也完全能理解。
此时在 master 分⽀上,我们对 Upload ⽂件再进⾏⼀次修改,并进⾏提交:
在这里插入图片描述
现在, master 分⽀和 dev1 分⽀各⾃都分别有新的提交,变成了这样:
在这里插入图片描述
)

这种情况下,Git 只能试图把各⾃的修改合并起来,但这种合并就可能会有冲突,如下所⽰:
在这里插入图片描述此时我们打开Upload文件:
在这里插入图片描述
此时我们必须要⼿动调整冲突代码,并需要再次提交修正后的结果:
在这里插入图片描述
到这⾥冲突就解决完成,此时的状态变成了:
在这里插入图片描述

此时我们查看提交日志时发现:
在这里插入图片描述
这个跟我们画的图几乎是一摸一样的。也就是说使用这种非Fast-forward模式是可以区分是合并修改还是只是master修改的,更加方便追责哈哈。

最后,不要忘记 dev1 分⽀使⽤完毕后就可以删除了:
在这里插入图片描述

3.7 🍎分⽀管理策略🍎

通常合并分⽀时,如果可能,Git 会采⽤Fast forward模式。还记得如果我们采⽤ Fast forward 模式之后,形成的合并结果是什么呢?
在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是 merge 进来的还是正常提交的?

但在合并冲突部分,我们也看到通过解决冲突问题,会再进⾏⼀次新的提交。那么这就不是 Fast forward 模式了,这样的好处是,从分⽀历史上就可以看出分⽀信息。

Git ⽀持我们强制禁⽤Fast forward模式,那么就会在 merge 时⽣成⼀个新的 commit ,这样从分⽀历史上就可以看出分⽀信息。

下⾯我们实战⼀下--no-ff⽅式的 git merge 。⾸先,创建新的分⽀ dev2 ,并切换⾄新的分⽀:

在这里插入图片描述
切回 master 分⽀,开始合并:
在这里插入图片描述请注意--no-ff参数,表⽰禁⽤ Fast forward 模式。禁⽤ Fast forward 模式后合并会创建⼀个新的 commit ,所以加上-m参数,把描述写进去(ps:不管是使用ff模式还是非ff模式,在多个分支下进行修改时都有可能会出现冲突,需要用户自己手动处理冲突)。
合并后,查看分⽀历史:
在这里插入图片描述
在这里插入图片描述
所以在合并分⽀时,加上--no-ff参数就可以⽤普通模式合并,合并后的历史有分⽀,能看出来曾经做过合并,⽽ fast forward 合并就看不出来曾经做过合并。


4 🍑分⽀策略🍑

在实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理:
⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活。
那在哪⼲活呢?⼲活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布时,再把dev分⽀合并到master上,在master分⽀发布1.0版本;你和你的⼩伙伴们每个⼈都在dev分⽀上⼲活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就可以了。
所以,团队合作的分⽀看起来就像这样:
在这里插入图片描述

4.1 🍎bug 分⽀🍎

假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有 bug,需要解决。在Git中,每个 bug 都可以通过⼀个新的临时分⽀来修复,修复后再合并分⽀,然后将临时分⽀删除。
可现在 dev2 的代码在⼯作区中开发了⼀半,还⽆法提交,怎么办?例如:
在这里插入图片描述
Git 提供了git stash命令,可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时间恢复出来。
在这里插入图片描述
⽤ git status 查看⼯作区,就是⼲净的(除⾮有没有被 Git 管理的⽂件),因此可以放⼼地创建分⽀来修复bug。
储藏 dev2 ⼯作区之后,由于我们要基于master分⽀修复 bug,所以需要切回 master 分⽀,再新建临时分⽀来修复 bug,⽰例如下:
在这里插入图片描述
修复完成后,切换到 master 分⽀,并完成合并,最后删除 solve_bug 分⽀:
在这里插入图片描述
⾄此,bug 的修复⼯作已经做完了,我们还要继续回到 dev2 分⽀进⾏开发。切换回 dev2 分⽀:
在这里插入图片描述
⼯作区是⼲净的,刚才的⼯作现场存到哪去了?⽤git stash list命令看看:
在这里插入图片描述
⼯作现场还在,Git 把 stash 内容存在某个地⽅了,但是需要恢复⼀下,如何恢复现场呢?我们可以使⽤git stash pop命令,恢复的同时会把 stash 也删了,⽰例如下:
在这里插入图片描述再次查看的时候,我们已经发现已经没有现场可以恢复了:
在这里插入图片描述

另外,恢复现场也可以采⽤git stash apply恢复,但是恢复后,stash内容并不删除,你需要⽤git stash drop来删除;你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}

恢复完代码之后我们便可以继续完成开发,开发完成后便可以进⾏提交,例如:
在这里插入图片描述

但我们注意到了,修复 bug 的内容,并没有在 dev2 上显⽰。此时的状态图为:
在这里插入图片描述

Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们在 dev2 中当然看不⻅修复 bug 的相关代码。

我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合并即可,但这样其实是有⼀定⻛险的。
是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。
此时的状态为:
在这里插入图片描述

解决这个问题的⼀个好的建议就是:最好在⾃⼰的分⽀上合并下 master ,再让 master 去合并dev2 ,这样做的⽬的是有冲突可以在本地分⽀解决并进⾏测试,⽽不影响 master 。
在这里插入图片描述

4.2 🍎删除临时分⽀🍎

软件开发中,总有⽆穷⽆尽的新的功能要不断添加进来。
添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新功能,最好新建⼀个分⽀,我们可以将其称之为 feature 分⽀,在上⾯开发,完成后,合并,最后,删除该 feature 分⽀。

可是,如果我们今天正在某个 feature 分⽀上开发了⼀半,被产品经理突然叫停,说是要停⽌新功能的开发。虽然⽩⼲了,但是这个 feature 分⽀还是必须就地销毁,留着⽆⽤了。这时使⽤传统的git branch -d命令删除分⽀的⽅法是不⾏的。演⽰如下:
在这里插入图片描述
然后我们切换到master分支进行删除:
在这里插入图片描述
使用这种方式是失败的,我们需要使用-D选项:
在这里插入图片描述


5 🍑远程操作🍑

5.1 🍎理解分布式版本控制系统🍎

我们⽬前所说的所有内容(⼯作区,暂存区,版本库等等),都是在本地!也就是在你的笔记本或者计算机上。⽽我们的 Git 其实是分布式版本控制系统!什么意思呢?
可以简单理解为,我们每个⼈的电脑上都是⼀个完整的版本库,这样你⼯作的时候,就不需要联⽹了,因为版本库就在你⾃⼰的电脑上。既然每个⼈电脑上都有⼀个完整的版本库,那多个⼈如何协作呢?⽐⽅说你在⾃⼰电脑上改了⽂件A,你的同事也在他的电脑上改了⽂件A,这时,你们俩之间只需把各⾃的修改推送给对⽅,就可以互相看到对⽅的修改了。

分布式版本控制系统的安全性要⾼很多,因为每个⼈电脑⾥都有完整的版本库,某⼀个⼈的电脑坏掉了不要紧,随便从其他⼈那⾥复制⼀个就可以了。
在实际使⽤分布式版本控制系统的时候,其实很少在两⼈之间的电脑上推送版本库的修改,因为可能你们俩不在⼀个局域⽹内,两台电脑互相访问不了。也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有⼀台充当“中央服务器”的电脑,但这个服务器的作⽤仅仅是⽤来⽅便“交换”⼤家的修改,没有它⼤家也⼀样⼲活,只是交换修改不⽅便⽽已。有了这个“中央服务器”的电脑,这样就不怕本地出现什么故障了(⽐如运⽓差,硬盘坏了,上⾯的所有东西全部丢失,包括git的所有内容)

5.2 🍎新建远程仓库🍎

在这里插入图片描述从创建好的远程仓库中我们便能看到,之前在本地学习过的分⽀,也存在于远程仓库中并被管理起来了。刚创建的仓库有且只有⼀个默认的master分⽀
在这里插入图片描述

5.3 🍎克隆远程仓库🍎

克隆/下载远端仓库到本地,需要使⽤git clone命令,后⾯跟上我们的远端仓库的链接,远端仓库的链接可以从仓库中找到:选择“克隆/下载”获取远程仓库链接:
在这里插入图片描述
SSH 协议和 HTTPS 协议是 Git 最常使⽤的两种数据传输协议。SSH 协议使⽤了公钥加密和公钥登陆机制,体现了其实⽤性和安全性,使⽤此协议需要将我们的公钥放上服务器,由 Git 服务器进⾏管理。使⽤ HTTPS ⽅式时,没有要求,可以直接克隆下来。

5.3.1 🍋使⽤ HTTPS ⽅式🍋

在这里插入图片描述
我们进入到仓库里面看看:
在这里插入图片描述

5.3.1 🍋使⽤ SSH ⽅式🍋

我们重新创建一个仓库:
在这里插入图片描述
此时我们直接克隆会直接报错:
在这里插入图片描述
使⽤ SSH ⽅式克隆仓库,由于我们没有添加公钥到远端库中,服务器拒绝了我们的 clone 链接。需要我们设置⼀下:

  • 1️⃣第⼀步:创建SSH Key。在⽤⼾主⽬录下,看看有没有.ssh⽬录,如果有,再看看这个⽬录下有没有id_rsa 和 id_rsa.pub 这两个⽂件,如果已经有了,可直接跳到下⼀步。如果没有,需要创建SSH Key:
    在这里插入图片描述
    顺利的话,可以在⽤⼾主⽬录⾥找到 .ssh ⽬录,⾥⾯有 id_rsa 和 id_rsa.pub 两个⽂件,这两个就是SSH Key的秘钥对, id_rsa 是私钥,不能泄露出去, id_rsa.pub 是公钥,可以放⼼地告诉任何⼈.
    在这里插入图片描述
  • 2️⃣第⼆步:添加⾃⼰的公钥到远端仓库。
    我们将公钥进行复制,然后在远程仓库里面添加公钥:
    在这里插入图片描述
    输入密码验证成功后即可:
    在这里插入图片描述
    此时我们进行克隆就成功了:
    在这里插入图片描述
    如果有多个⼈协作开发,GitHub/Gitee 允许添加多个公钥,只要把每个⼈的电脑上的Key 都添加到 GitHub/Gitee,就可以在每台电脑上往 GitHub/Gitee 上提交推送了。

当我们从远程仓库克隆后,实际上 Git 会⾃动把本地的 master 分⽀和远程的 master 分⽀对应起来,并且,远程仓库的默认名称是 origin 。在本地我们可以使⽤git remote命令,来查看远程库的信息,如:
在这里插入图片描述
上⾯显⽰了可以抓取和推送的origin的地址。

5.4 🍎向远程仓库推送🍎

本地已经 clone 成功远程仓库后,我们便可以向仓库中提交内容,例如新增⼀个 test.txt文件:
先配置好用户名和邮箱:
在这里插入图片描述
注意你这里的用户名要跟gitup/gitee用户名保持一致。然后进行add和commit即可。
到这⾥我们已经将内容提交⾄本地仓库中,如何将本地仓库的内容推送⾄远程仓库呢,需要使⽤git push命令,
该命令⽤于将本地的分⽀版本上传到远程并合并,命令格式如下:

git push <远程主机名> <本地分⽀名>:<远程分⽀名>
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号:
git push <远程主机名> <本地分⽀名>

此时我们要将本地的 master 分⽀推送到 origin 主机的 master 分⽀,则可以:
在这里插入图片描述此时我们在远端仓库进行查看:
在这里插入图片描述

5.5 🍎拉取远程仓库🍎

为了方便演示,我直接将远端仓库的内容进行修改(不建议大家这么做):
在这里插入图片描述
此时,远程仓库是要领先于本地仓库⼀个版本,为了使本地仓库保持最新的版本,我们需要拉取下远端代码,并合并到本地。Git 提供了git pull命令,该命令⽤于从远程获取代码并合并本地的版本。格式如下:

git pull <远程主机名> <远程分⽀名>:<本地分⽀名>
2
3 # 如果远程分⽀是与当前分⽀合并,则冒号后⾯的部分可以省略。
4 git pull <远程主机名> <远程分⽀名>

在这里插入图片描述
我们发现,拉取成功了!

5.6 🍎配置 Git🍎

5.6.1 🍋忽略特殊⽂件🍋

在⽇常开发中,我们有些⽂件不想或者不应该提交到远端,⽐如保存了数据库密码的配置⽂件,那怎么让 Git 知道呢?在 Git ⼯作区的根⽬录下创建⼀个特殊的.gitignore⽂件,然后把要忽略的⽂件名填进去,Git 就会⾃动忽略这些⽂件了。不需要从头写 .gitignore ⽂件,gitee 在创建仓库时就可以为我们⽣成,不过需要我们主动勾选⼀下.
由于在创建时我添加了C++的一些常用忽略文件。所以打开.gitignore效果就是这样:

在这里插入图片描述
此时我们是无法将忽略文件提交到暂存区的。
但有些时候,你就是想添加⼀个⽂件到 Git,但由于这个⽂件被 .gitignore 忽略了,根本添加不了,那么可以⽤-f强制添加:

git add -f [filename]

或者你发现,可能是 .gitignore 写得有问题,需要找出来到底哪个规则写错了,⽐如说 a.so ⽂件是要被添加的,可以⽤git check-ignore命令检查。此时Git 会告诉我们, .gitignore 的哪一⾏规则忽略了该⽂件,于是我们就可以知道应该修订哪个规则。

还有些情况我们不想要某个文件被忽略,在.gitignore规则外的写法就是 ! +⽂件名,所以,只需把例外⽂件添加进去即可。

# 不排除.gitignore
!.gitignore

5.6.2 🍋给命令配置别名🍋

在我们使⽤ Git 期间,有些命令敲的时候着实让⼈头疼(太⻓了。。),幸运的是,git⽀持对命令进⾏简化!
举个例⼦,将 git status 简化为 git st ,对应的命令为:

git config --global alias.st status

--global 参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有⽤。如果不加,那只针对当前的仓库起作⽤。

5.7 🍎标签管理🍎

标签 tag ,可以简单的理解为是对某次 commit 的⼀个标识,相当于起了⼀个别名。例如,在项⽬发布某个版本的时候,针对最后⼀次 commit 起⼀个 v1.0 这样的标签来标识⾥程碑的意义。

这有什么⽤呢?相较于难以记住的 commit id , tag 很好的解决这个问题,因为 tag ⼀定要给⼀个让⼈容易记住,且有意义的名字。当我们需要回退到某个重要版本时,直接使⽤标签就能很快定位到。

在Git中打标签⾮常简单,⾸先,切换到需要打标签的分⽀上:
在这里插入图片描述
然后,敲命令git tag [name]就可以打⼀个新标签,可以⽤命令git tag查看所有标签:
在这里插入图片描述

默认标签是打在最新提交的commit上的。那如何在指定的commit上打标签呢?⽅法是找到历史提交的commit id,然后打上就可以了,⽰例如下:
在这里插入图片描述
注意,标签不是按时间顺序列出,⽽是按字⺟排序的。
可以⽤git show [tagname]查看标签信息。
在这里插入图片描述
Git 还提供可以创建带有说明的标签,⽤-a指定标签名,-m指定说明⽂字,格式为:

git tag -a  <tagname> -m "XXX" [commit_id]

如果标签打错了,也可以删除,使用 git tag -d [name]命令即可。

因为创建的标签都只存储在本地,不会⾃动推送到远程。所以,打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使⽤命令 git push origin <tagname>
在这里插入图片描述
此时在远端就能够看见推送过来的标签:
在这里插入图片描述
当然,如果你本地有很多标签,也可以⼀次性的全部推送到远端:

git push origin --tags

如果标签已经推送到远程,要删除远程标签就⿇烦⼀点,先从本地删除使用git tag -d命令,然后,从远程删除。删除命令也是push,但是格式如下:

git push origin :refs/tags/v1.0

6 🍑多⼈协作🍑

6.1 🍎场景一🍎

为了方便演示,分别在 linux 和 windows 上针对于同项⽬进⾏协作开发(使用linux 和 windows 来模拟不同成员的协作)。

⽬前,我们的仓库中只有⼀个 master 主分⽀,但在实际的项⽬开发中,在任何情况下其实都是不允许直接在 master 分⽀上修改代码的,这是为了保证主分⽀的稳定。所以在开发新功能时,常常会新建其他分⽀,供开发时进⾏迭代使⽤。
那么接下来,就让我们在 gitee 上新建 dev 远程分⽀供我们使⽤:

在这里插入图片描述
创建成功的远程分⽀是可以通过 Git 拉取到本地来,以实现完成本地开发⼯作。
在Linux下:
我们首先将远程仓库中的分支给拉取下来:
在这里插入图片描述
然后使用git branch -r命令查看远程分⽀:
在这里插入图片描述

拉取后便可以看到远程的 dev 分⽀,接着切换到 dev 分⽀供我们进⾏本地开发。要说明的是,我们切换到的是本地的 dev 分⽀,根据⽰例中的操作,会将本地分⽀和远程分⽀的进⾏关系链接。

在Windows下:
我们首先将远程仓库中的分支给拉取下来:
在这里插入图片描述
然后进行查看:
在这里插入图片描述

后面我们就可以在dev上进行开发了。将Windowsxp和Linux中工作分支都切换到dev。

现在Linux上进行推送:
在这里插入图片描述
在这里插入图片描述
上面操作都是之前已经讲过了的,这里就不再多说了。此时我们观察远端仓库:

在这里插入图片描述

然后我们切换到Windows中:
我们找到对应的目录使用记事本打开文件进行修改:
在这里插入图片描述
我们发现此时打开是没有在Linux中增加的数据,这是符合预期的,因为我们拉取的代码本来就是在开始的版本。
然后进行推送:
在这里插入图片描述
发现此时推送会出现冲突,解决办法也很简单,Git已经提⽰我们,先⽤git pull把最新的提交从 origin/dev 抓下来,然后,在本地进⾏合并,并解决冲突,再推送。操作如下:
在这里插入图片描述
此时我们打开记事本,进行修改:
在这里插入图片描述
修改后成了这样:
在这里插入图片描述
然后进行重新推送:
在这里插入图片描述
此时已经推送成功,我们在远端下观察:
在这里插入图片描述
最后不要忘记,虽然我们是在分⽀上进⾏多⼈协作开发,但最终的⽬的是要将开发后的代码合并到master上去,让我们的项⽬运⾏最新的代码。接下来我们就需要做这件事情了。
我们可以使用远端的方式来进行合并,但这里我们使用命令的方式来进行合并帮助大家理解:
首先我们要切换⾄ master分⽀, pull ⼀下,保证本地的master是最新内容, 合并前这么做是⼀个好习惯:
在这里插入图片描述

然后 切换⾄ dev 分⽀, 合并 master 分⽀,这么做是因为如果有冲突,可以在dev分⽀上进⾏处理,⽽不是在master上解决冲突,这么做是⼀个好习惯。
在这里插入图片描述
最后切换⾄ master 分⽀,合并 dev 分⽀,并将mastet推送至远端:
在这里插入图片描述

然后在远端下观察,master已经是最新代码了:

在这里插入图片描述
dev 分⽀对于我们来说就没⽤了, 那么 dev 分⽀就可以被删除掉。我们可以直接在远程仓库中将dev分⽀删除掉:
在这里插入图片描述删除后只剩master了:
在这里插入图片描述然后在本地我们也可以手动删除dev分支了。这里就不再演示了,之前讲解过。

总结⼀下,在同⼀分⽀下进⾏多⼈协作的⼯作模式通常是这样:

  • ⾸先,可以试图⽤ git push origin branch-name 推送⾃⼰的修改;
  • 如果推送失败,则因为远程分⽀⽐你的本地更新,需要先⽤ git pull 试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突后,再⽤git push origin branch-name推送就能成功;
  • 功能开发完毕,将分⽀ merge 进 master,最后删除分⽀。

6.2 🍎场景二🍎

场景一的情况在日常开发中应该时很少见的,一般来说场景二更为常见些。

如果有多需求需要多⼈同时进⾏开发,是不会在⼀个分⽀上进⾏多⼈开发,⽽是⼀个需求或⼀个功能点就要创建⼀个 feature 分⽀。
现在同时有两个需求需要你和你的⼩伙伴进⾏开发,那么你们俩便可以各⾃创建⼀个分⽀来完成⾃⼰的⼯作。在上个部分我们已经了解了可以从码云上直接创建远程分⽀,其实在本地创建的分⽀也可以通过推送的⽅式发送到远端。在这个部分我们就来⽤⼀下这种⽅式。

在场景一下我们是在远端创建了新分支然后拉取到本地的,现在我们换一种方式,在本地建立新的分支来推送到远端。
在Linux下:
首先新增本地分⽀ feature-1 并切换:
在这里插入图片描述
然后新增需求内容,创建function1⽂件,并将 feature-1 分⽀推送到远端:
在这里插入图片描述
在Windows下也是进行相同的操作:
在这里插入图片描述

在这里插入图片描述

此时在远端下观察:
在这里插入图片描述
正常情况下,你俩就可以在⾃⼰的分⽀上进⾏专业的开发了!
但天有不测⻛云,你的⼩伙伴突然⽣病了,但需求还没开发完,需要你帮他继续开发,于是他便把feature-2 分⽀名告诉你了。这时你就需要在⾃⼰的机器上切换到 feature-2 分⽀帮忙继续开发,要做的操作如下:
首先必须先拉取远端仓库内容:
在这里插入图片描述
然后切换到feature-2分⽀上,可以和远程的feature-2分⽀关联起来,否则将来只使⽤git push推送内容会失败:

 git checkout -b feature-2 origin/feature-2

在这里插入图片描述查看远程状态,推送成功了:
在这里插入图片描述
这时,你的⼩伙伴已经修养的差不多,可以继续进⾏⾃⼰的开发⼯作,那么他⾸先要获取到你帮他开发的内容,然后接着你的代码继续开发。或者你已经帮他开发完了,那他也需要在⾃⼰的电脑上看看你帮他写的代码:
首先拉取最新代码:
在这里插入图片描述

但是我们查看文件内容时发现并没有成功:
在这里插入图片描述
pull ⽆效的原因是⼩伙伴没有指定本地 feature-2 分⽀与远程 origin/feature-2 分⽀的链接,根据提⽰,设置feature-2和origin/feature-2的链接即可:
在这里插入图片描述
此时发现拉取成功:
在这里插入图片描述

⽬前,⼩伙伴的本地代码和远端保持严格⼀致。你和你的⼩伙伴可以继续在不同的分⽀下进⾏协同开发了。
各⾃功能开发完毕后,不要忘记我们需要将代码合并到master中才算真正意义上的开发完毕。
由于你的⼩伙伴率先开发完毕,于是开始merge
首先切换至master,pull一下,保证本地master是最新的内容:
在这里插入图片描述

然后切换至featrue-2分支,拉取最新代码,然后合并master:
在这里插入图片描述

切换至master分支,合并featrue-2:
在这里插入图片描述
最后将master分支推向远端:
在这里插入图片描述

此时远程仓库的状态:
在这里插入图片描述当你的⼩伙伴将其代码 merge 到 master 后,这是你也开发完成了,也需要进⾏ merge 到master 操作,于是你:
首先切换⾄ master分⽀, pull ⼀下,保证本地的master是最新内容,合并前这么做是⼀个好习惯:

在这里插入图片描述
然后切换⾄ feature-1 分⽀, 合并 master 分⽀,这么做是因为如果有冲突,可以在feature-1分⽀上进⾏处理,⽽不是在在master上解决冲突,这么做也是⼀个好习惯:
在这里插入图片描述

在这里插入图片描述要注意的点:由于feature-1分⽀已经merge进来了新内容,为了保证远程分⽀最新,所以最好push⼀下;要 push 的另⼀个原因是因为在实际的开发中,master的merge操作⼀般不是由我们⾃⼰在本地进其他⼈员或某些平台merge时,操作的肯定是远程分⽀,所以就要保证远程分⽀的最新;如果 merge 出现冲突,不要忘记需要commit才可以push。
在这里插入图片描述

切换⾄ master 分⽀,合并 feature-1 分⽀:

在这里插入图片描述
最后将 master 分⽀推送⾄远端:
在这里插入图片描述
此时远程仓库的状态:
在这里插入图片描述
此时, feature-1 和 feature-2 分⽀对于我们来说就没⽤了, 那么我们可以直接在远程仓库中将分⽀删除掉。

但是远程分⽀删除后,本地git branch -a依然能看到:
在这里插入图片描述

当前我们已经删除了远程的⼏个分⽀,使⽤git branch -a命令可以查看所有本地分⽀和远程分⽀,但发现很多在远程仓库已经删除的分⽀在本地依然可以看到。

使⽤命令git remote show origin,可以查看remote地址,远程分⽀,还有本地分⽀与之相对应关系等信息。
在这里插入图片描述此时我们可以看到那些远程仓库已经不存在的分⽀,根据提⽰,使⽤ git remote prune origin 命令:

在这里插入图片描述
这样就删除了那些远程仓库不存在的分⽀。对于本地仓库的删除,之前的课程已经学过了,⼤家可以⾃⾏操作。

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值