Skip to content

06玩转Git命令,搞定团队协作

上节课我们一起学习了 Python 的高阶编程知识,本课时我将向你讲解 Git 的使用方法,以及如何使用 Git 搞定团队协作。

Git 简述

如果说功能测试工程师的日常工作被测试用例文档和执行用例包围,那么测试开发工程师的日常工作就要从代码提交上说起了。

在高度协作化的今天,由于效率的因素,即使是测试平台,一个人完成一个系统的全部开发这种模式逐渐变得不再适用;如今大部分情况,测试开发任务会被分解成一个个模块,分别由不同的人负责,这就带来了以下问题:

  • 假设你和别人负责同一个页面的不同模块,你们的代码应该如何提交整合?

  • 假设你要修改一段公用代码,而别人正好也在修改了这个代码,这个代码如何提交?以及如何保存?

  • 假设一个功能经过多次代码演变后再被你接手,你想看下这块代码的演变历史,该怎么办?

说到这里,我相信你肯定明白了,我们需要版本控制系统来追踪代码的历史演变过程,从而更好地解决上述可能的冲突。

作为市面上最好的开源分布式版本控制系统,Git 就闪亮登场了。那么 Git 为什么这么受追捧呢? 这与它的原理有很大关系。

1. 高效的数据存储方式

与其他版本控制软件不同,Git 并不以文件变更列表的方式存储信息(该类版本控制方式也叫基于差异(delta-based)的版本控制),而是采用快照流的方式对信息进行存储。

在 Git 中,当你提交、更新时, Git 会对项目的全部文件创建一个快照并保存这个快照的索引;当你再次提交、更新时,如果存在没有修改的文件,则 Git 只保留一个链接指向之前存储的文件,而不再重新存储该文件,这样就提高了存储效率。

2. 几乎所有操作都是本地执行

在 Git 中, 绝大多数操作都只需要访问本地文件和资源而无须联网。因为 Git 是分布式的,所以你的本地磁盘上就有项目的完整历史。

这种独特的方式可以使你在离线时也能进行 Git 操作并且提交数据,而用 Subversion 和 CVS 的话, 你能修改文件,但不能向数据库提交修改(因为你的本地数据库离线了)。

3. 具备数据完整性保障

在 Git 中,你的任何操作在被存储前都会使用SHA-1散列(Hash,哈希)计算校验和(checksummed)来保障数据的完整性。(例如,你的每个 commit ID 的信息就是一个 SHA-1 Hash 值)。

在实际工作中,我们通过 GitHub、Bitbucket 或者 GitLab 这样的云服务平台来管理项目,大型的公司也会通过在内部搭建私有 Git 仓库的方式来管理,无论是哪种方式,背后都离不开 Git。

Git 工作流程

1.Git 中的三种文件状态

在 Git 里,你的项目文件可能处于以下三种状态之一:

  • 已修改(modified),表示修改了文件,但还没保存到数据库中;

  • 已暂存(staged),表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中;

  • 已提交(committed),表示数据已经安全地保存在本地数据库中。

2.Git 项目的三个阶段

相应地,我们的 Git 项目就分别对应着三个阶段: 工作区、暂存区和 Git 目录。

  • 工作区

工作区是从 Git 仓库提取出来的数据,也就是我们本地看到的代码目录,这里改动的代码都在已修改状态。

  • 暂存区

暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。当处于已修改状态的文件被放入暂存区(Git Add)时,这些文件则会变为已暂存状态。

  • Git 目录

Git 仓库目录是 Git 用来保存项目的元数据和对象数据库 的地方。从其他计算机克隆仓库时,复制的就是这里的数据。当暂存区的文件被提交(Git Commit),则这些文件属于已提交状态。

Git 项目的阶段图

3. Git 基本工作流程

了解了这些,我们来看下 Git 的基本工作流程:

  • 工作区进行代码新建、修改、删除;

  • 将你下次要提交的改动全部或者选择性的暂存到暂存区(Git Add);

  • 提交你的改动(Git Commit)。

Git 实践

当你了解了 Git 的基本知识后,就可以开始实践了。

1.Git 安装

使用不同操作系统的安装方式各有不同。

  • Mac 系统安装

在 Mac 系统下可以直接使用 homebrew 安装:

java
brew install git

如果 homebrew 没有安装,则可以采用如下方式安装 homebrew 后再执行上述命令:

java
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
  • Window 系统安装

在 Window 系统下安装,可直接点击访问 Git 网站下载安装包进行安装:

  • Linux 系统安装

在 Linux 系统下,可以直接通过输入如下命令行进行安装:

java
$ sudo dnf install git-all
  • Ubuntu 系统安装

在 Ubuntu 系统下,你可以通过输入如下命令行进行安装:

java
$ sudo apt install git-all

2.Git 设置

在安装 Git 后,一般要进行用户设置,因为你的每一次 Git 提交都需要用户信息,你可以采用如下步骤配置你的信息。

  • 打开命令行工具:

若你使用的是 Windows 系统,通过"win+ R"快捷键组合,然后输入"cmd"进入;

若你使用的是 Mac 系统,则通过"Command + 空格",然后输入"Terminal"的方式。

  • 输入如下命令:
java
#设置你的Git提交的用户名
$ git config --global user.name "Kevin Cai"
#设置你的邮箱地址
$ git config --global user.email TesterTalk@outlook.com
  • 通过如下命令查看是否设置成功:
java
$ git config --list

当你设置好用户信息后,以后通过 Git 提交代码,Git 会自动使用你配置的用户信息进行提交。

3.Git 基本操作

好了,现在我们已经了解了 Git 的原理并已经安装好 Git,下面就来看看 Git 的基本操作吧。

正常情况下,公司的代码都是通过 GitHub 企业版或者 GitLab 来进行托管。我以 GitHub 为例,来讲解下 Git 的使用和协作交互(GitLab 大体相同)。

还记得我在 "课前必读2 | 测试开发的职业生涯是怎样的?" 中讲过的测试开发流程吗?我把有关Git 操作的部分截取过来:

可以看到,涉及代码提交的步骤有:

  • Task 开发,开发人员在本地 feature 分支进行功能开发;

  • 提交测试,新功能开发完成后,开发人员在本地分支自测,然后通过 pull request 的方式提交代码;

  • 测试验证,GitHub 根据条件自动触发测试验证流程;

  • 代码 Merge,测试通过后,代码被 Merge 到 master 分支。

如上流程几乎是各个互联网公司通用的开发协作流程,下面我就来详细讲解 Task 开发中的 Git 操作及其作用。

要进行 Task 开发,就必须有相应的 Git 项目,那么 Git 项目如何生成呢?

一般情况下,都是直接拉取已经存在的项目,而在拉取项目之前,你最好配置下 SSH,SSH 协议用来连接远程服务器和服务并向它们认证,使用 SSH 连接 GitHub 无须每次访问都提供用户名和密码。

配置 SSH 的方法直接参考 GitHub 官网链接即可,配置好 SSH 后,你可以直接通过如下命令拉取你的项目。

  • git init

如果是创建全新的项目,你可以通过如下方式:

shell
#首先,通过命令行进入到你想创建 Git 仓库的目录,然后再目录下执行
$ git init

例如你在文件夹 lagouTest 下执行 git init,则 git 将在 lagouTest 下创建一个 .git 子目录,这意味着 lagouTest 这个目录已经转变成了一个 Git 仓库,我们可以对它进行版本管理了。

  • git add .

如果是通过 git init 立的项目,此时你的 Git 仓库是空的,你可以通过新建文件的方式来编写你的代码,比如新建一个 newcase.py 并且编写。等你编写好后,可以通过 git add 的方式将它提交到暂存区。

shell
#把本地文件newcase.py的改变提交到暂存区
$ git add newcase.py
#如果更改的文件过多,可以直接把本地所有的改变提交到暂存区
$ git add .
  • git rm

当你想删除某个文件时,可以使用 git rm

shell
# 删除文件
$ git rm <file>
#删除README file
$ git rm README
  • git status

如果你想查看当前版本库的状态,可以使用 git status

shell
$ git status

git status 将列出文件/文件夹在工作区和暂存区的状态。

  • git commit -m

接着把暂存区的改动提交到本地版本库。

shell
# 通过-m参数输入本次提交的改动信息,方便我们了解本次的代码变更
$ git commit -m "我的第一次提交"
  • git remote add

项目要多人协作就必须把本地仓库提交到远程。

shell
#如下语法用来添加一个远程仓库
$ git remote add [shortname] [url]
#将本地仓库lagouTest和远程仓库建立连接
$ git remote add origin https://github.com/yourCompany/lagouTest.git

如果是新建立的项目,需要用这个方式建立远程仓库。待远程仓库建好后,还需要将本地的改动通过 git push 到远程去。

  • git push - u

既然是团队协作就必须把本地版本库上传到远程库,这样别的开发人员才能拉取你的改动。

shell
# 如果是本地新仓库第一次push到远程,你需要执行如下操作
$ git push -u origin master

通过上述方式,你的代码已经存在远程仓库的 master 分支了,别的开发人员就可以拉取你的代码进行修改了。

  • git clone

要通过 git 协作,首先要 clone 远程仓库到本地。

shell
#在命令行中执行如下操作
$ git clone 你的项目地址
# 譬如,如下命令将Copy lagouTest到本地。
$ git clone https://github.com/yourCompany/lagouTest.git
  • git checkout-b

项目被拉取到本地后,开发人员就可以进行分支开发,通常情况下不会在 master 分支进行开发,而是采取新 feature 分支开发的方式。

shell
#创建并切换feature分支
$ git checkout -b newFeature

假如分支 newFeature 已经存在,你想要切换到这个分支工作,则使用如下命令:

shell
$ git checkout newFeature

当 feature 分支创建好后,开发人员就可以新建代码文件并进行代码的编写;代码编写好后,开发人员就会提交,此时仍然采用 "git add" 和 "git commit"提交即可;当你 commit 后,也要提交到远程仓库。

  • git push-set-upstream

因为我们是本地创建的 feature 分支,远程并没有对应的分支,故需要远程分支关联。

shell
# 把本地分支newFeature关联到远程分支origin
$ git push --set-upstream origin newFeature

此时远程分支除去 master 分支外,还有我们新建立的 newFeature 分支。当关联远程分支后,我们在 newFeature 分支上再做任何改动,需要 push 到远程分支,就可以直接使用 "git push" 而无须再次进行关联。

shell
# newFeature的再次改动提交到远程库,仅需执行git push即可。
$ git push
  • pull request

pull request(通常被简称为 PR)是 GitHub 的一个通知机制,通过它开发人员可以进行更好的协作。pull request 通常要指定 reviewer(评审者),它告诉项目成员我的 feature 功能开发已经完毕,希望合并到代码主分支(master)。

创建 PR 通常是使用 GitHub 界面完成的。仍然拿项目 lagouTest 为例,我们需要把 feature 分支 newFeature 上的改动 merge 到 master,就需要提交 pull request。

在 GitHub 项目目录选择 "compare & pull request" 来建立一个 pull request。

在创建 pull request 页面,可以看到我们是要把 newFeature 的改动 merge 到 master 里去。正文的输入框中,输入本次提交都修改了哪些内容,然后在右侧的 Reviewers 里添加需要协作的同事,然后点击 "Create pull request" 即可。

提交后你的同事会收到邀请,当他们 Approve 你的改动后,你的代码就进入了 master 仓库(关于如何 review 一个 pull request,请参考 Review Pull Request)。

  • git branch -d

当你的分支被 merge 后,你的 feature 分支和远程分支就不需要了,最好把它们删除以保持 git 分支的清爽。

shell
#删除本地分支
$ git branch -d [branchname]
#譬如删除本地分支newFeature
$ git branch -d newFeature
#删除远程分支
$ git push origin --delete [branchname]
# 删除远程分支newFeature
$ git push origin --delete newFeature

Git 常见问题

除了上述 Git 常用的操作外,在日常工作和面试中,我们经常会遇见如下问题。

1. 如何查看提交历史

当你需要查看某个文件的提交历史时,使用如下命令:

shell
$ git log filename
#查看 newcases.py的提交历史
$ git log newcases.py

2. 本地正在开发,远程 master 有了更新,如何应用更新到本地分支?

当远程有更新且需要应用到本地时,可以采用如下操作:

shell
# 假设本地feature分支为newFeature
# 首先需要提交本地分支newFeature的改动至代码仓库
$ git add .
$ git commit -m "本地分支修改comments"
# 然后,执行git merge
$ git merge master
# 最后,再次提交
$ git add .
$ git commit -m "merge master 分支"

3. 提交时文件有冲突怎么办?

当多人同时改动一个文件并且当你提交时,这个文件已经被先行 merge 到 master 时,就会出现冲突。

当出现冲突后, git 会列出来冲突的内容,你可以通过手动选择保留哪个版本的方式来解决冲突,解决冲突后,通过"git add" 和"git commit"再次提交即可。

4. 当你正在进行分支开发时,接到一个紧急任务,如何将当前的改动保留和后续恢复?

当你的 feature 分支开发了一半,然后接到了紧急任务需要支持,但是你又不想把功能不完善的代码提交到代码仓库,此时可以使用 git stash 命令。

shell
# 如果你要切换新分支但是有未保存的更改使用git checkout -b会报错。此# 时可以通过git stash将所有未提交的修改(工作区和暂存区)保存至堆栈# # 中,可用于后续恢复.
$ git stash
# 等你想恢复你保存的改动时,执行git stash pop。 它将缓存堆栈中的第一个stash删除,并将对应修改应用到当前的工作目录下。
$ git stash pop

5. 本地提交已提交到暂存区,但是不想要了怎么办?

假设你的某次改动已经提交到暂存区,还没有 push,但是你想丢弃这个改动,可以采用如下办法:

shell
$ git reset --hard HEAD

git reset 有 hard 和 soft 两个模式,感兴趣的同学可以自行了解下其中的区别。

6. 提交后发现把本次修改的内容写错了,怎么办?

当你只想 git commit 后发现遗漏或者写错了本次修改的内容, 可以采用如下方式:

shell
$ git commit --amend
# git会出现一个编辑框,你可以更改你的提交信息。

7. 上线后有问题,代码需要回退怎么办?

如果发现发布上线的功能有问题,需要回退的情况,执行如下操作:

shell
$ git revert HEAD
$ git push origin master

小结

本节课我介绍了 Git 的原理、用法和常见问题。Git 命令本身比较多,也难以全部熟记,在工作中,我们常用的就是 git init、git add、git commit、git push、git merge 这几个命令,把这些常用的命令记清楚,有助于你快速地进行团队协作。

为了方便大家记忆 git 命令,我将本节所讲内容制作成一个表格,供大家查阅。


"测试开发工程师名企直推营"入口,免费领取 50G 资料包