Jean's Blog

一个专注软件测试开发技术的个人博客

0%

Git分布式控制软件

Git

什么是版本控制?

版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一 。— 百度百科

什么是集中化的版本控制系统?

就是有一个集中管理的中央服务器,保存着所有文件的修改历史版本,而协同开发者通过客户端连接到这台服务器,从服务器上同步更新或上传自己的修改。

image-20220720112403501

什么是分布式版本控制系统?

分布式版本控制系统,就是远程仓库同步所有版本信息到本地的每个用户。

  • 用户在本地就可以查看所有的历史版本信息,但是偶尔要从远程更新一下,因为可能别的用户有文件修改提交到远程哦。
  • 用户即使离线也可以本地提交,push推送到远程服务器才需要联网。
  • 每个用户都保存了历史版本,所以只要有一个用户设备没问题,就可以恢复数据。

image-20220720112434611

Git介绍

image-20201015113819789

Git官网

git是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)(Linux之父)创作,于2005年发布。最初目的是为更好地管理Linux内核开发。Git 在本地磁盘上就保存着所有有关当前项目的历史更新,处理速度快;Git 中的绝大多数操作都只需要访问本地文件和资源,不用实时联网。

安装

  • Linux:sudo apt-get install git
  • Mac:brew install git
  • Windows:官网下载安装包

Git的相关理论基础

Git的四大工作区域

  1. Workspace:你电脑本地看到的文件和目录,在Git的版本控制下,构成了工作区。
  2. Index/Stage:暂存区,一般存放在 .git目录下,即.git/index,它又叫待提交更新区,用于临时存放你未提交的改动。比如,你执行git add,这些改动就添加到这个区域啦。
  3. Repository:本地仓库,你执行git clone 地址,就是把远程仓库克隆到本地仓库。它是一个存放在本地的版本库,其中HEAD指向最新放入仓库的版本。当你执行git commit,文件改动就到本地仓库来了~
  4. Remote:远程仓库,就是类似github,码云等网站所提供的仓库,可以理解为远程数据交换的仓库~

image-20220720112654120

Git的工作流程

执行操作如下:

  1. 首先我们先从远程仓库克隆(clone)到本地仓库;
  2. 从远程仓库拉取文件到本地仓库,在工作目录中进行增删改查文件;
  3. 提交文件到本地仓库,我们需要先通过 add 命令将文件放入暂存区中;
  4. 通过 commit 命令将文件放入到本地仓库中;
  5. 我们通过 push 命令将文件从本地仓库推送到远程仓库中;
  6. 更新别人提交的代码需要我们通过 pull 命令将代码更新到工作区;

image-20220720114148553

Git文件的四种状态

根据一个文件是否已加入版本控制,可以把文件状态分为:Tracked(已跟踪)和Untracked(未跟踪),而tracked(已跟踪)又包括三种工作状态:Unmodified,Modified,Staged。

image-20220720114238844

  • Untracked: 文件还没有加入到git库,还没参与版本控制,即未跟踪状态。这时候的文件,通过git add 状态,可以变为Staged状态。
  • Unmodified:文件已经加入git库, 但是呢,还没修改, 就是说版本库中的文件快照内容与文件夹中还完全一致。Unmodified的文件如果被修改, 就会变为Modified. 如果使用git remove移出版本库, 则成为Untracked文件。
  • Modified:文件被修改了,就进入modified状态啦,文件这个状态通过stage命令可以进入staged状态。
  • staged:暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodified状态。

Git的工作原理

image-20220720114330221

Git初使用

配置用户名和邮箱

  • git config —global user.name “xxx” — 用于查看 Git 提交记录,方便查看谁操作的,可以随便设置,不建议随便设置。
  • git config —global user.email “xxx” — 用于查看 Git 提交记录,方便查看谁操作的,可以随便设置,不建议随便设置。
  • git config -l / git config —list 查看已配置的信息

操作演示

最常用的命令流程:

  • git init 在指定文件夹下执行,之后该文件夹会变成一个git仓库。也可以通过 git init 仓库名称 来创建。

  • git status 查看 Git 仓库的状态,主要是查工作区和暂存区有没有文件。

  • git add 文件名 将文件添加到暂存区中。

  • git commit 文件名 -m ‘注释内容’ 将文件添加到本地仓库中并产生历史版本记录 ;

  • git log 查看当前分支历史提交记录。

设置ssh-key

Git 服务器都会选择使用 SSH 公钥来进行授权。系统中的每个用户都必须提供一个公钥用于授权,没有的话就要生成一个。生成公钥的过程在所有操作系统上都差不多。

生成SSH公钥命令如下:

1
ssh-keygen -t rsa -C“youremail@xxx.com"

执行命令后需要进行 3 次或 4 次确认:

  • 确认秘钥的保存路径(如果不需要改路径则直接回车);
  • 如果上一步置顶的保存路径下已经有秘钥文件,则需要确认是否覆盖(如果之前的秘钥不再需要则直接回车覆盖,如需要则手动拷贝到其他目录后再覆盖);
  • 创建密码(如果不需要密码则直接回车);
  • 确认密码。

ssh-key路径

  • Windows 默认 ssh-key 路径默认:C:/Users/用户名/.ssh
  • Mac 默认 ssh-key 路径默认:/Users/用户名/.ssh

Git常用命令

Git基本命令使用流程

image-20220720114421008

克隆远程版本库

  • git clone url 克隆远程版本库

创建分支

  • git checkout -b dev 创建开发分支dev,并切换到该分支下

创建工程

将本地的工程创建为git仓库

  • 文件根目录下:git init

添加到暂存区

  • git add
    • git add . 添加当前目录的所有文件到暂存区
    • git add [dir] 添加指定目录到暂存区,包括子目录
    • git add [file1] 添加指定文件到暂存区
    • git add -u 提交所有被删除和修改的文件到数据暂存区
    • git add -A 提交所有被删除、被替换、被修改和新增的文件到数据暂存区

提交暂存区到仓库区

  • git commit
    • git commit -m [message] 提交暂存区到仓库区,message为说明信息
    • git commit [file1] -m [message] 提交暂存区的指定文件到本地仓库
    • git commit —amend -m [message] 使用一次新的commit,替代上一次提交
    • git commit -am ‘注释内容’ 相当于执行 git add -u + git commit -m ‘注释内容’。前提是该文件已经执行过 git add 操作。

查看工作区状态

  • git status
    • git status 查看当前工作区暂存区变动
    • git status -s 查看当前工作区暂存区变动,概要信息
    • git status —show-stash 查询工作区中是否有stash(暂存的文件)

查看提交历史/日志

  • git log
    • git log 查看提交历史
    • git log —all 查看所有分支的提交历史记录
    • git log —oneline 以精简模式显示查看提交历史
    • git log -p <file> 查看指定文件的提交历史
    • git blame <file> 一列表方式查看指定文件的提交历史
    • git log -n 2 查看最近2次提交的历史记录
    • git log -p -2 最近两次提交差异显示
    • git log —pretty=oneline 查看简洁提交历史记录

查看暂存区和工作区的差异

  • git diff
    • git diff 显示暂存区和工作区的差异
    • git diff filepath filepath路径文件中,工作区与暂存区的比较差异
    • git diff HEAD filepath 工作区与HEAD ( 当前工作分支)的比较差异
    • git diff branchName filepath 当前分支的文件与branchName分支的文件的比较差异
    • git diff commitId filepath 与某一次提交的比较差异

拉取远程分支仓库分支到本地

  • git pull/git fetch
    • git pull 拉取远程仓库所有分支更新并合并到本地分支。
    • git pull origin master 将远程master分支合并到当前本地分支。
    • git pull origin master:master 将远程master分支合并到当前本地master分支,冒号后面表示本地分支。
    • git fetch —all 拉取所有远端的最新代码
    • git fetch origin master 拉取远程最新master分支代码
  • git pull和git fetch的区别
    • git pull = git fetch + git merge
      • pull的话,拉取远程分支并与本地分支合并
      • fetch只是拉远程分支,怎么合并,可以自己再做选择

推送到远程分支

  • git push 可以推送本地分支、标签到远程仓库,也可以删除远程分支哦

    • git push origin master 将本地分支的更新全部推送到远程仓库master分支。

    • git push origin -d <branchname> 删除远程branchname分支

    • git push —tags 推送所有标签

文件删除和修改名称操作

  • git rm + git mv
    • git rm 文件名称 从工作目录中删除该文件并且本地不保留。
    • git rm —cached 文件名称 从版本控制中删除该文件,但在本地保留该文件(相当于将文件从暂存区撤销到工作区中)
    • git mv 原来名称 新的名称 更改文件名并提交到本地仓库 (暂存区和本地仓库文件)本地仓库需要再次执行 commit 提交

Git分支管理

git branch用处多多,比如新建分支、查看分支、删除分支等等

新建分支

  • git checkout -b dev2 新建一个分支,并且切换到新的分支dev2
  • git branch dev2 新建一个分支,但是仍停留在原来分支

查看分支

  • git branch 查看本地所有的分支
  • git branch -r 查看所有远程的分支
  • git branch -a 查看所有远程分支和本地分支

删除分支

  • git branch -D <branchname> 删除本地branchname分支 -d/-D

切换分支

  • git checkout master 切换到master分支

分支合并

  • git merge

    • git merge master 在当前分支上合并master分支过来

    • git merge —no-ff origin/dev 在当前分支上合并远程分支dev

    • git merge —abort 终止本次merge,并回到merge前的状态

Git处理冲突

Git 解决冲突步骤如下:

1. 查看冲突文件内容

  • git merge提示冲突,切换到对应文件,查看冲突内容cat xxx.java

2. 确定冲突内容保留哪些部分,修改文件

  • Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容
  • <<<<<<<HEAD是指主分支修改的内容,>>>>>>>dev是指dev分支上修改的内容

3. 重新提交

  • 修改完冲突文件内容,重新提交

Git撤销与回退

Git的撤销与回退,在日常工作中使用的比较频繁。比如我们想将某个修改后的文件撤销到上一个版本,或者想撤销某次多余的提交,都要用到git的撤销和回退操作。

代码在Git的每个工作区域都是用哪些命令撤销或者回退的呢,如下图所示:

image-20220720114550538

撤销

  • git checkout 如果文件还在工作区,还没添加到暂存区,可以使用git checkout撤销
    • git checkout [file] 丢弃某个文件file
    • git checkout . 丢弃所有文件

重置

reset

  • git reset 作用是修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本

    • Git的版本管理及HEAD的理解:

      • Git的所有提交,会连成一条时间轴线,这就是分支。如果当前分支是master,HEAD指针一般指向当前分支,如下:

      image-20220720114709062

      • 假设执行git reset,回退到版本二之后,版本三不见了,如下:

      image-20220720114755796

    • git reset的几种使用模式

      • git reset HEAD —file 回退暂存区里的某个文件,回退到当前版本工作区状态
      • git reset –-soft 目标版本号 可以把版本库上的提交回退到暂存区,修改记录保留
      • git reset –-mixed 目标版本号 可以把版本库上的提交回退到工作区,修改记录保留
      • git reset –-hard 可以把版本库上的提交彻底回退,修改的记录全部revert

      image-20220720114840658

revert

  • git revert

    • 与git reset不同的是,revert复制了那个想要回退到的历史版本,将它加在当前分支的最前端

      • revert之前

      image-20220720114931079

      • revert之后

      image-20220720115003515

    • 如果代码已经推送到远程的话,还可以考虑revert回滚

      • git log 得到你需要回退一次提交的commit id
      • git revert -n <commit_id> 撤销指定的版本,撤销也会作为一次提交进行保存

Git标签tag

打tag就是对发布的版本标注一个版本号,如果版本发布有问题,就把该版本拉取出来,修复bug,再合回去。

  • git tag 列出所有tag
  • git tag [tag] 新建一个tag在当前commit
  • git tag [tag] [commit] 新建一个tag在指定commit
  • git tag -d [tag] 删除本地tag
  • git push origin [tag] 推送tag到远程
  • git show [tag] 查看tag
  • git checkout -b [branch] [tag] 新建一个分支,指向某个tag

Git一些经典命令

git rebase

rebase又称为衍合,是合并的另外一种选择。使用讲解如下:

假设有两个分支master和test

1
2
3
     D---E test
/
A---B---C---F--- master

执行 git merge test得到的结果

1
2
3
      D--------E
/ \
A---B---C---F----G--- test, master

执行git rebase test,得到的结果

1
A---B---D---E---C‘---F‘---   test, master

常用一些命令:

  • git rebase -i commit_id
  • pick:保留该commit(缩写:p)
  • reword:保留该commit,但我需要修改commit的注释(缩写:r)
  • edit:保留该commit,但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
  • squash:将该commit和前一个commit合并(缩写:s)
  • fixup:将该commit和前一个commit合并,但不要保留该提交的注释信息(缩写:f)
  • exec:执行shell命令(缩写:x)
  • drop:丢弃该commit(缩写:d)

rebase好处是: 获得更优雅的提交树,可以线性的看到每一次提交,并且没有增加提交节点。所以很多时候,看到有些伙伴都是这个命令拉代码:git pull —rebase,就是因为想更优雅。

git stash

stash命令可用于临时保存和恢复修改

  • git stash 把当前的工作隐藏起来 等以后恢复现场后继续工作
  • git stash list 显示保存的工作进度列表
  • git stash pop stash@{num} 恢复工作进度到工作区
  • git stash show :显示做了哪些改动
  • git stash drop stash@{num} :删除一条保存的工作进度
  • git stash clear 删除所有缓存的stash。

git reflog

显示当前分支的最近几次提交

git blame filepath

git blame 记录了某个文件的更改历史和更改人

git remote

  • git remote 查看关联的远程仓库的名称
  • git remote add url 添加一个远程仓库
  • git remote show [remote] 显示某个远程仓库的信息

Git commit日志规范

commit日志结构规范:

1
2
3
4
5
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

type代表某次提交的类型,比如是修复一个bug还是增加一个新的feature。

所有的type类型如下:

type 说明
feat 新增feature
perf 优化相关,比如提升性能、体验
refactor 代码重构,没有加新功能或者修复bug
fix 修复bug
test 测试用例,包括单元测试、集成测试等
style 仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑
chore 改变构建流程、或者增加依赖库、工具、数据库脚本等
docs 仅仅修改了文档,比如README, CHANGELOG, CONTRIBUTE等等
revert 回滚到上一个版本

格式要求:

1
2
3
4
5
6
7
8
9
10

# 标题行:50个字符以内,描述主要变更内容
#
# 主体内容:更详细的说明文本,建议72个字符以内。 需要描述的信息包括:
#
# * 为什么这个变更是必须的? 它可能是用来修复一个bug,增加一个feature,提升性能、可靠性、稳定性等等
# * 他如何解决这个问题? 具体描述解决问题的步骤
# * 是否存在副作用、风险?
#
# 尾部:如果需要的化可以添加一个链接到issue地址或者其它文档,或者关闭某个issue。

PS:当某次提交的内容较多时,应当将提交内容进行一下分类,然后分多次进行提交。最好是在开发过程中如果完成了一个完整的工作内容,立马进行commit