摘要:
  本文主要介绍Git中的基本命令以及beyond compare插件的介绍。

【说明】:

一、Git配置命令

1.查看版本

1
git --version

2.设置用户信息

1
2
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

  安装完 Git 之后,要做的第一件事就是设置你的用户名邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到每一次提交中,不可更改

  如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论在该系统上做任何事
情, Git 都会使用那些信息。 当想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。

3.设置文本编辑器

1
git config --global core.editor emacs # Vim、Emacs 和 Notepad++ 都是流行的文本编辑器

  Windows 系统上,如果想要使用别的文本编辑器,那么必须指定可执行文件完整路径

4.检查配置信息

1
git config --list  # 列出所有 Git 当时能找到的配置

  此命令运行后可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。若想检查某一项配置信息,则可以:

1
git config <key> # 获取某一项配置信息

5.对LFCRLF的处理

  Linux系统和Windows系统下的换行符不一样,Linux\n,即LFWindows下面是\r\n,即CRLFgit在维护版本库的时候统一使用的是LF。所以当文档跨平台进行编辑的时候,换行符就会产生差别,在不同平台编辑过得文件在进行commit的时候也会有相应的换行符警告。

1
LF will be replaced by CRLF in .......

那么怎么处理呢?这样就可以了(不过这样似乎只是治标不治本,仅仅是忽略了检查,要是文章的话还好,要是代码的话,有可能会因为换行符而出现问题,暂时先这样解决)。

1
git config --global core.autocrlf false

6.查看配置及配置所在文件

1
git config --list --show-origin

  该命令可以查询 Git 中该变量的 原始 值,它会告诉我们哪一个配置文件最后设置了该值。

7.获取帮助

1
2
3
git help <verb>      # verb 为想要查询的命令,如 config
git <verb> --help # verb 为想要查询的命令,如 config
man git-<verb> # verb 为想要查询的命令,如 config

  若不需要全面的手册,只需要可用选项的快速参考,那么可以用-h选项获得更简明的 help输出

1
git <verb> -h        # verb 为想要查询的命令,如 config,add

二、Git——本地仓库

  本部分介绍Git在本地仓库中进行版本控制的相关操作。

1.Git在本地三大工作区域

image-20220110145428667

2.基本命令

2.1初始化文件夹

1
2
3
4
# 进入或者创建想要初始化的文件夹
cd ~/3MyGitFiles/
# 初始化
git init
image-20220110150103283

  如上图所示,初始化完成后会出现图中的提示,初始化的过程中Git 会创建一个 .git 目录。 这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可,新初始化的.git目录结构如下。

image-20220110150513919

2.2检查文件状态

1
2
vim a.md # 首先创建一个文件,运行后,按 :wq 保存并退出 
git status # 查看当前文件夹中文件状态
image-20220110150819365

  我们先创建一个新的文件,不做任何操作,使用该命令,发现Git已经检测到该文件,当文件还未被提交到暂存区的时候显示为红色

  git status 命令的输出十分详细,但输出有些繁琐。Git 有一个选项可以缩短状态命令的输出,这样可以以简洁的方式查看更改,如下图所示。

1
2
git status -s       # 使用该命令查看状态
git status --short # 或者使用该命令
image-20220110151912273
标记 说明
?? 新添加的未跟踪文件(红色)
A 新添加到暂存区中的文件(绿色)
M 修改过的文件(红色)
AM 已添加到暂存区的文件又被修改了(A绿色,M红色)
UU 由合并分支引起冲突,修改文件后还未添加到暂存区的状态标记(红色)

2.3管理文件

  就是把文件添加到暂存区,.表示当前目录下所有文件,也可以只管理某一个文件,后边换成文件名称即可。

1
2
git add .            # 添加所有文件
git add <file_name> # 添加指定文件,可以同时指定多个文件
image-20220110152213824

【注意】文件添加到暂存区的时候,会由红色变为绿色。

  此时我们修改a.md文件,再查看状态,再提交到暂存区,这个时候文件状态的变化如下图所示:

image-20220110152559490

  在添加到暂存区之前,修改后的文件标记变成了AM的标记,A就表示之前已经提交到暂存区了,M表示提交后,又修改了此文件,当修改后再次提交,文件标记就会重新变成A

###2.4生成版本

  在本阶段,将把暂存区域的数据提交到本地的版本库中 ,命令中的描述是提交时写的提交说明,可以会更清楚的看到自己每次做了哪些修改,便于日志的查看。

1
git commit -m "描述"

2.4查看提交的版本记录

1
git log
image-20220110153305417

  如图中所示,会显示提交的版本号,可以通过此版本号恢复到任一提交状态,HEAD表示当前指向的分支,就是当前提交是提交到了哪一个分支上,还会显示提交的作者信息,就是之前绑定的时候的信息,说明一点,当没有进行提交作者信息绑定的情况下,该命令会报错,需要注意一下。

  git log命令的其他参数

参数 描述
--oneline 把每一个提交信息压缩为一行
--stat 通过比较每个提交展示插入与删除的数量
-p 看每个提交实际的变化
--graph 绘制一幅表示分支结构提交历史的ASCII图。该选项通常会结合 --oneline 与 --decorate 一起使用,使得能更加容易地看出提交所属的分支
--pretty=format:" <格式字符串> " 可以让我们使用 printf 风格的占位符来展示每条提交。
详情可查看:PRETTY FORMATS

【格式字符串】

选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期( --date = 制定的格式)
%cr 提交日期,按多久以前的方式显示(1 day ago)
%s 提交说明
%d ref 名称
%n 换行

【说明】在选项前边加上%C(color)则可以分别指定输出内容的颜色,color可选的值有reset(默认的灰色),normal, black, red, green, yellow, blue, magenta, cyan, white。另外说明一点就是color最好就是可以**带上圆括号()**,这样既清晰,也不会出错。

1
2
3
4
5
git log --oneline  # 把每一个提交信息压缩为一行
git log --stat # 通过比较每个提交展示插入与删除的数量
git log -p # 看每个提交实际的变化
git log --graph --oneline --decorate # 绘制一幅表示分支结构提交历史的ASCII图
git log --pretty=format:"%Cgreen%an %Cred%h %Cblue%s" # 以不同颜色显示提交者名字、提交说明和简短的哈希字符串

2.5定制git log

1
2
3
4
# 个人定制版 git log
git log --graph --pretty=format:'%C(magenta)[%an]%C(reset) %C(red)%h%C(reset) : %C(green)%s%C(reset) %C(yellow)%d%C(reset) %C(blue)(%cr)%C(reset) ' --abbrev-commit --date=relative # 相对时间

git log --graph --pretty=format:'%C(magenta)[%an]%C(reset) %C(red)%h%C(reset) : %C(green)%s%C(reset) %C(yellow)%d%C(reset) %C(blue)(%cd)%C(reset) ' --abbrev-commit --date=format:'%Y-%m-%d %H:%M:%S' # 绝对时间

【说明】一般来说format后边跟的是双引号",但是若想使用alias创建自定义命令的话,需要改为**单引号'**,否则会报错。

  • 自定义方法一:修改~/.gitconfig文件
1
vim ~/.gitconfig

  打开后在结尾处添加以下内容:

1
2
[alias]
mylog = log --graph --pretty=format:'%C(magenta)[%an]%C(reset) %C(red)%h%C(reset) : %C(green)%s%C(reset) %C(yellow)%d%C(reset) %C(blue)(%cr)%C(reset)' --abbrev-commit --date=relative
  • 自定义方法二:命令行输入
1
git config --global alias.mylog "log --graph --pretty=format:'%C(magenta)[%an]%C(reset) %C(red)%h%C(reset) : %C(green)%s%C(reset) %C(yellow)%d%C(reset) %C(blue)(%cr)%C(reset)' --abbrev-commit --date=relative"
  • 运行自定义命令
1
git mylog
  • 效果
image-20220110174851259

3.小故事学操作

  首先,介绍一下背景哈,后边可能会沿用这个故事来进行Git的学习,从而在不同场景下练习Git操作。

  long long ago ...,有一个孩子,叫Hector他学的专业是自动化这一方面的,他有一个朋友,名字是Andrea。这天Hector叫来Andrea说,我们做一个环境检测系统用于参加比赛吧,Andrea马上表现出极大的热情,于是,他们进行了各种调研之后,便开始进行这个项目的实践,项目名称就定为environment

3.1开始项目工程

  • 1.创建项目文件夹并进行Git初始化
1
2
3
mkdir ~/environment    # 创建项目工程文件夹
cd ~/environment
git init
  • 2.创建程序文件
1
2
cd ~/environment
touch program.c
  • 将所有文件添加到本地版本库以便于版本控制
1
2
3
4
git status -s  # 查看文件状态
git add . # 添加所有文件到暂存区
git commit -m "Create related files." # 提交文件到本地版本库
git mylog # 查看提交记录,该命令为自己定制,具体可以看2.6节

【说明】为了作下一节的修改上次提交命令测试,这里删掉了之前的.git文件,重新进行了初始化和提交,所以hash值与上边的图片有所区别,后边都以新提交的为准。

image-20220110211411391

3.2修改上次提交

  提交完了,发现忘记创建说明文档了,即readme.md文件没有创建和提交。 那么怎么解决呢?可以重新提交一次,但是这就意味着版本库中有两个提交记录,这样的情况出现的多了,就会导致版本库历史记录很乱,我们既想将该文件提交上去,又不想让提交记录变得繁琐,那么要怎么样解决呢?此时,可以运行带有--amend选项的提交命令来重新提交,这样可以避免让仓库历史纪录变得复杂。

  • 命令格式
1
2
git commit --amend -m "新的描述" # 如果不加-m参数,系统会让进行输入的
git commit --amend --no-edit # 不修改描述,只是添加新文件
  • 实际操作
1
2
3
git add readme.md
git commit --amend --no-edit # 重新提交
git mylog # 查看提交记录,该命令为自己定制,具体可以看2.6节
image-20220110212545086

  由图可知,提交记录还是只有一条,提交的描述也未发生变化,但是提交时间和提交的hash值却更新了,其实按自己理解,就相当于撤销了上一次提交,将文件全部重新提交了一次。

3.3回到指定版本

  当某一项功能正在开发的时候,发现这一项功能不需要了,如果想要回到之前的功能,而去掉正在开发的东西,一个比较麻烦的方法就是将上一个功能完成后新增加的东西全部删除,但是这样的话工作量极其巨大,那么我们要怎么做呢?Git的版本回滚功能就很好的解决了这个问题。

  • 命令格式
1
2
git reflog               # 查看所有提交记录
git reset --hard <版本号> # 回到指定版本,版本号即为每次提交的hash值

【说明】:

  其实这里查看所有提交记录的时候,也可以使用git log(或者定制指令git mylog)指令来查看,那么该指令与git reflog区别在哪里呢?

  git reflog命令可以查看所有分支的所有操作记录信息,包括已经被删除的 commit 记录和 reset 的操作。

  git log命令可以显示当前分支所有提交过的版本信息,不包括已经被删除的 commit 记录和reset的操作。(注意: 只是当前分支操作的信息)。

  所以,当我们回滚版本回滚错了的时候,想要恢复回滚之前的版本的话,git reflog就为该操作的实现提供了可能。

  • 实际操作

  到目前为止,Hector的环境检测项目已经开发了两个功能:温度检测(Temperature detection)和湿度检测(Humidity detection)两个功能,并且每个功能完成时都进行了单独的提交。

文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
提交记录 image-20220110221729303

(1)回到温度检测版本

  项目在一段时间后要向老师演示功能,但是老师说湿度检测功能不需要了,也不需要演示,同时湿度检测功能还有些小问题,为了完美展示温度检测功能,最好就是删除湿度检测功能,这就需要回滚版本到只开发了温度检测的时候了。

1
2
git mylog          # 此处使用 mylog,以便于后边作对比
git reset --hard bf5d364
文件名称 文件内容
program.c 1.Temperature detection
readme.md 1.温度检测功能开发完毕
提交记录 image-20220110223445564

  可以发现,版本回到了温度开发的版本,文件也发生了相应的变化,从提交记录中也可以看出git loggit reflog的区别。

(2)回到湿度检测开发版本

  湿度检测也是环境检测的一项功能,虽然说老师并未要求,但是要是能做出来,这样也是极好的。但是两人一想,完了,刚才不是回到温度检测版本,把湿度检测的历史纪录删掉了吗?他们就要重新开发嘛?那不是很浪费时间,那有没有什么方法呢?当然有,依然是使用上边回到指定版本的命令,但是需要知道版本号啊,这怎么办呢?Git为用户提供了另外一个查看版本提交历史纪录的命令。

1
git reflog

  该命令就可以显示出所有的提交记录,包括已经删除的,所以运行以下命令可得表中数据。

文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
提交记录 image-20220110225140989

 可以发现,又回到了拥有湿度开发的版本。

3.4分支的应用

  • 概念

  分支的大概原理思路,如下流程图中,V1V2只是保存了修改信息,而不是复制了原程序,再进行开发,在V2节点,在新功能B开发过程中,V2出现了BUG,这个时候需要保留B的新功能,而又要修复BUG,此时可以新建分支修复BUG,此时在BUG C1中进行修复,新功能B也可以正常开发,当完成之后将他们都合并到主分支上去。分支的存在就保证了可以份个除开单独的空间做其他的事情,不同的分支不会互相影响。
  所以在使用Git进行版本控制的时候建议创建至少两个分支,主分支用于正式版本程序发布,另外分支用于版本的更新迭代。

1
2
3
4
5
6
graph LR
A[主程序]
A1[V1]--版本升级-->A
A2[V2]--版本升级-->A1[V1]
B1[新功能B]--新功能开发-->A2[V2]
C1[BUG C1]--修复BUG-->A2[V2]
  • 命令格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
git branch <branch name>   # 创建分支

git checkout <branch name> # 切换分支

git checkout -b <branch name> # 创建并切换到创建的分支

git merge <branch name> # 合并分支(要先切换回要合并到的分支)

git branch -d <branch name> # -d 删除已合并分支

git branch -D <branch name> # -D 强制删除分支,不管是否已经合并

git branch # 得到当前所有分支的一个列表

git branch -v # 查看每一个分支的最后一次提交

git branch --merged # 查看哪些分支已经合并到当前分支

git branch --no-merged # 查看所有包含未合并工作的分支

【注意】

  1.在进行分支的切换或者其他操作时,一定要保证所有的文件都已经在本地版本库中被管理,也就是说,一定要提交所有文件之后再进行分支操作,否则可能会带来意想不到的问题。

  2.新的分支创建之后所有分支的内容、提交记录等完全一样

  • 实际操作

  上文说道,他们已经恢复了湿度检测功能的相关代码,随后也修复了湿度检测功能的小问题,所以接下来要继续开发新动能,光照强度检测功能。但不幸的是,纲要进行新功能开发,湿度检测功能就出现了BUG,需要进行修复,但是新功能的开发也不能停下,修复BUG和新功能开发要同时进行,并且不能互相影响,他们这个时候就需要用到分支的功能了。

【分支创建】

1
2
3
4
5
# 创建分支
git branch newfunction # 用于新功能开发
git branch bug # 用于修复bug
# 查看当前所有分支
git branch
image-20220111112256553

可以发现,已经创建了新的分支,但是目前还是在主分支master

【新功能开发部分】

(1)切换到newfunction分支

1
git checkout newfunction
image-20220111112757931

(2)开始光照强度检测功能开发

  切换到newfunction分支后,便可以进行新功能开发了,修改完相应文件后进行提交。

1
2
3
4
git status -s
git add .
git commit -m "Light intensity detection."
git mylog
文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection

3.Light intensity detection
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕

3.光照强度检测功能开发完毕
提交记录 image-20220111113216612

BUG修复部分】

(1)切换到BUG分支

1
git checkout bug
image-20220111113445755

可以发现,不同的分支是相互独立,互不影响的。

(2)开始BUG修复

  切换到BUG分支后,便可以进行BUG修复了,修改完相应文件后进行提交。

1
2
3
4
git status -s
git add .
git commit -m "BUG fix."
git mylog
文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
  bug1--->Restored
  bug2--->Restored
  bug3--->Restored
  bug4--->Restored
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
  bug1--->已修复
  bug2--->已修复
  bug3--->已修复
  bug4--->已修复
提交记录 image-20220111114426711

【合并分支部分】

  当新功能和BUG修复的相关程序都已经完成时,就需要进行分支的合并了。

(1)切换回master分支

1
git checkout master

(2)查看master分支相关文件及提交记录

文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
提交记录 image-20220111114909730

可以发现,所有文件及提交记录并未发生变化。

(3)合并BUG分支到master

  要注意将一个分支合并到另一个分支的时候,要提前切换回另一个分支。

1
2
3
4
# 确保切换回master分支
git checkout master
# 合并分支
git merge bug
文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
  bug1--->Restored
  bug2--->Restored
  bug3--->Restored
  bug4--->Restored
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
  bug1--->已修复
  bug2--->已修复
  bug3--->已修复
  bug4--->已修复
提交记录 image-20220111115224354

发现文件与BUG分支的内容保持一致,提交记录也多了BUG分支的提交记录。

(4)合并newfunction分支到master

1
2
3
4
# 确保切换回master分支
git checkout master
# 合并分支
git merge newfunction

  此时,问题出现了,如下图所示。

image-20220111115543384

  从结果可知,文件合并时出现了冲突,那么接下来,就看一看master分支的文件内容及提交记录是怎样的。

文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
<<<<<<< HEAD
  bug1--->Restored
  bug2--->Restored
  bug3--->Restored
  bug4--->Restored
=======

3.Light intensity detection
>>>>>>> newfunction
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
<<<<<<< HEAD
  bug1--->已修复
  bug2--->已修复
  bug3--->已修复
  bug4--->已修复
=======

3.光照强度功能开发完毕
>>>>>>> newfunction
提交记录 image-20220111120142018

  从文件内容分析,创建了两个分支,这样的话三个分支的内容完全一致,在每个分支进行的操作,修改等互不影响。但是,在git中,这三个分支实际上使用的是同一个文件,同一个文件的同一行在不同的分支中代表不同的内容时,我们又要进行合并,那么此时内容会进行合并,都会显示在文件中,但是就会出现冲突以及冲突点的标记,这个时候需要我们手动来确认文件内容。从提交记录分析,合并分支后出现冲突,newfunction分支上的提交记录并未一起合并过来。那么接下来,我们就修改文件,重新提交。

文件名称 文件内容
program.c 1.Temperature detection

2.Humidity detection
  bug1--->Restored
  bug2--->Restored
  bug3--->Restored
  bug4--->Restored

3.Light intensity detection
readme.md 1.温度检测功能开发完毕

2.湿度检测功能开发完毕
  bug1--->已修复
  bug2--->已修复
  bug3--->已修复
  bug4--->已修复

3.光照强度功能开发完毕
提交记录 image-20220111121644396

(5)删除已合并分支

1
2
git branch -d bug
git branch -d newfunction

3.5git rebase

3.5.1rebase介绍

  rebase中文名字叫变基,它主要有两个方面的应用,第一方面是合并提交记录,使提交变得简洁。第二个方面是用于整合分支。具体情况可以继续往下阅读,通过实例,可能会更容易理解些。

3.5.2应用场景一:合并提交记录

  rebase可以让提交历史变得简洁,试想一下,一个功能的开发需要将近一个月的时间才能完成,在这一个月中不可能一次都不提交,这样提交的多了,提交记录就会显得特别的冗杂,这可不是大家希望看到的,这时候就会想,要是提交记录能合并该多好,于是Git中的rebease就为这种想法提供了可能。

  要注意的就是,最好不要合并已经推送到**远程分支(后边再讲,这里先提一下)**的提交记录,否则会比较麻烦,可能会报以下错误:

1
error: cannot 'squash' without a previous commit
  • 命令格式
1
2
3
4
5
6
7
8
9
10
11
12
# 1.合并从当前开始的前n个记录(包括当前)
git rebase -i HEAD~n # n 为要合并的提交记录数

# 2. git调用编辑器,用户输入相应内容

# 3. 若是vim编辑器,则进入命令模式后用 :wq 保存退出
# 若是emacs(Git默认编辑器),则按照屏幕下方的提示进行保存退出

# 4. 其他相关命令
git rebase --edit-todo # 异常退出编辑器时,该命令可重新打开编辑器
git rebase --continue
git rebase --abort # 终止变基(终止合并提交记录)

编辑器中的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 命令:
# p, pick <提交> == 使用提交
# r, reword <提交> == 使用提交,但编辑提交说明
# e, edit <提交> == 使用提交,但停止以便在 shell 中修补提交
# s, squash <提交> == 使用提交,但挤压到前一个提交
# f, fixup [-C | -c] <提交> == 类似于 "squash",但只保留前一个提交
# 的提交说明,除非使用了 -C 参数,此情况下则只
# 保留本提交说明。使用 -c 和 -C 类似,但会打开
# 编辑器修改提交说明
# x, exec <命令> == 使用 shell 运行命令(此行剩余部分)
# b, break = 在此处停止(使用 'git rebase --continue' 继续变基)
# d, drop <提交> = 删除提交
# l, label <label> = 为当前 HEAD 打上标记
# t, reset <label> = 重置 HEAD 到该标记
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . 创建一个合并提交,并使用原始的合并提交说明(如果没有指定
# . 原始提交,使用注释部分的 oneline 作为提交说明)。使用
# . -c <提交> 可以编辑提交说明。
#
# 可以对这些行重新排序,将从上至下执行。
#
# 如果您在这里删除一行,对应的提交将会丢失。
#
# 然而,如果您删除全部内容,变基操作将会终止。
#

【注意】:

  1.至少要有三次提交时才可以进行提交记录合并,也就是说,其他的提交记录不能与第一条提交记录合并,否则会报fatal: 无效的上游 'HEAD~2'

  2.在进入编辑器后,第一行的pick不要修改,其他的pick要改为s,这样提交记录才能进行合并,若是全部改为s则会报以下问题,出现该问题时,可以先终止,再重新合并。

image-20220111154643834
  • 实际操作

  HectorAndrea在完成光照强度检测功能开发后,进入了摄像头采集图像信息的功能开发,该部分工作量较大,他们提交了很多的历史记录,看着非常的复杂,现在,他们想把前期采集图像的提交记录合并,那么怎么操作呢?他们之前提交的相关提交记录如下:

image-20220111160758415

(1)合并提交记录命令

1
2
# 合并从当前开始的前两个记录(包括当前)
git rebase -i HEAD~3

(2)修改编辑器中命令

  按照图中标记的三步进行即可。

image-20220111161412252

(3)修改合并后的提交说明

  上一步完成后,会再次进入编辑器编辑模式,这一次是修改合并后需要显示的提交说明。

image-20220111162007516

(4)查看提交记录

1
git mylog
image-20220111162120258

  由图可知,合并完提交记录后,三次提交变成了一次,当有很多提交时,可以按照此方法进行合并,以使提交记录简洁明了。

3.5.3应用场景二:合并分支

  在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebasemerge我们之前已经使用过了,这里主要介绍rebase。在这里举一个栗子:如下图所示,图中箭头是反方向,原因就是看法不同,箭头朝右表示版本的更迭,箭头朝左表示后一个版本由前一个版本修改提交而来。

  主分支master上已经有了V0V1V2V3四个版本的提交历史,在V2版本的时候,新建了分支Dev,随后进行代码修改,进行一次提交,形成了V3版本的程序。

  对于功能开发分支Dev,它是从master分支上的V2版本处新建的分支,并进行了一次提交,形成了V4版本的提交记录。

  此时这两个分支还未进行任何操作,依然相互独立,互不影响。

image-20220111210355418

图3.5.3-1 两个分支的提交历史

(1)通过merge合并分支

image-20220111211716416

图3.5.3-2 merge合并分支以整合文件和提交历史

  整合分支最容易的方法是 merge 命令。 它会把两个分支的最新快照(V3V4)以及二者最近的共同祖先(V2)进行三方合并,合并的结果是生成一个新的快照(V5)(并提交)。这样做的结果就是通过git log --graph来打印提交记录的时候,会产生分叉,类似于这种:

1
2
3
*---*---*---*---*
\ /
--*--

(2)通过rebase合并

  若是在图3.5.3-1中,不使用merge,而是提取在Dev分支V4版本中引入的补丁和修改,然后在master分支上进行一次应用,也就是说将Dev分支V4中所作的修改直接添加到master分支的V3中。在 Git 中,这种操作就叫做变基(rebase。我们可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。

image-20220111213504887

图3.5.3-3 rebease将V4的修改变基到V3上

  执行以下命令,完成变基:

1
2
3
4
5
6
7
8
9
10
# 终端中输入的命令
git checkout Dev
git rebase master

# 终端中显示的提示(官方文档提供)
First, rewinding head to replay your work on top of it...
Applying: added staged command

# 终端中显示的提示(自己实践显示)
成功变基并更新 refs/heads/Dev。

  它的原理是首先找到这两个分支(即当前分支 Dev、变基操作的目标基底分支 master) 的最近共同祖先 V2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件, 然后将当前分支(Dev分支)指向目标基底(masterV3,最后以此将之前另存为临时文件的修改依序应用。【注意】此时在Dev分支中已经包含了master分支中V3的提交历史了,但是master分支依然处于V3

  回到master分支,进行一次快进合并(通过merge),注意此时也可能会有冲突出现,处理解决后正常提交一次即可。

1
2
git checkout master
git merge Dev
image-20220111215818312

  此时,V4'指向的快照就和图3.5.3-2中 V5 指向的快照一模一样了。 这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。 在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的, 但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。

1
*---*---*---*---*

  一般我们这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁——例如向某个其他人维护的项目贡献代码时。 在这种情况下,首先在自己的分支里进行开发,当开发完成时需要先将的代码变基到 origin/master 上,然后再向主项目提交修改。 这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。

  请注意,无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

【注意】更多例子请查看官网说明文档:官方文档:3.6 Git 分支 - 变基

  • 实际操作

  上节讲到,HectorAndrea已经完成了摄像头信息采集功能的提交记录合并,算是已经完成了图像采集功能。接着,他们要进行下一步了,开发新的功能二氧化碳浓度检测,而与此同时还要继续摄像头功能的下一步,完成检测到异常情况后拍摄照片功能。此时呢,他们新建了一个分支进行摄像头功能的下一步开发,新功能就直接在master分支上进行了开发,这样倒是没什么问题,但是通过merge就会使提交记录产生分叉,他们又不希望出现这样的情况,那么该怎么办呢?接下来,他们便尝试了rebase的方法。

【摄像头功能的继续开发(dev分支)】

(1)新建分支,并进行功能开发

1
2
git branch dev   # 新建分支
git checkout dev # 切换分支开始工作

(2)提交文件并查看提交记录

1
2
3
git add .
git commit -m "Camera takes pictures."
git mylog
image-20220111221722269

【二氧化碳浓度检测的新功能开发(master分支)】

(1)开发新功能

1
2
3
# 1.切换回master分支
git checkout master
# 2.修改文件

(2)提交文件并查看提交记录

1
2
3
git add .
git commit -m "CO2 concentration detection."
git mylog
image-20220111222618717

【通过merge合并】

  为了做一个对比,这里两种方法都进行尝试。

1
git merge dev
image-20220111222849245

  合并时,Git会打开设置的编辑器,让用户输入合并时的提交说明。

image-20220111223035993

  由图中可知,提交的历史的ASCII图 产生了分叉,为了下一步验证rebase,这里还需要回滚到未合并之前的时候。

1
git reset --hard 250f573
image-20220111223412509

【通过rebase合并】

(1)切换到dev分支并执行变基命令(rebase

1
2
3
4
5
6
# 切换到dev分支
git checkout dev
# 变基
git rebase master
# 查看带ASCII图的提交记录
git mylog

image-20220111223622816

  由图可知,master分支上的最新的提交(CO2 concentration detection.)也归入了dev分支。

(2)切换到master分支并进行一次快速合并(merge

1
2
3
4
git checkout master
git merge dev
# 查看带ASCII图的提交记录
git mylog
image-20220111224048902

  由图中可知,master上的提交不再分叉,就是一条直线的提交了。【注意】merge的时候还是有可能会产生冲突,解决冲突后重新进行一次提交即可

三、Git——远程仓库

1.Github是什么?

  GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。简单来说,GitHub是一个代码托管云服务网站,帮助开发者存储和管理其项目源代码,且能够追踪、记录并控制用户对其代码的修改。

2.Github能做什么?

  • 托管代码、历史版本管理
  • 搜索开源项目
  • 分享的同时会得到社区的回馈
  • 使用Github Pages服务,可以免费搭建一个博客网站
  • 学习,能力提升
  • 提升自己的影响力

3.GithubGit有什么关系?

  简单来说,Git只是一个命令行工具,一个分布式版本控制系统。正是它在背后管理和跟踪你的代码历史版本,好比一个时光机,让你在代码出错时不至于手忙脚乱,能快速回退之前的历史版本。 类似的工具还有SVN

  而GitHub是一个代码托管网站,背后使用Git作为版本管理工具(而非svn)。主要服务是将你的项目代码托管到云服务器上,而非存储在自己本地硬盘上。类似的网站还有gitlab.com,bitbucket.com,coding.com(国内),gitee.com(国内)

4.为什么要用Github托管代码?

  试想一下,当我们需要在两个不同且间隔很远的地方来回奔波,并且还要写代码的时候,代码在本地电脑里边,但是我们总不能到处都带着电脑吧,很简单的一个想法,我们可以用硬盘啊,或者云盘,保存一份代码,只带着硬盘或者从云盘里边下载,这样不就解决了携带电脑的不便问题了吗?没错,GitHub就是一个大型的托管平台,这个平台可以实现团队协作,也可以同步提交记录,无疑是提供了巨大的方便。

5.Github经常打不开怎么办?

5.1手动查询并修改hosts文件

【说明】也有可能没啥用,但是网上好多这种方法的说明。

  • 三个网址
GitHub网址IP查询 GitHub.com
GitHub域名查询 github.global.ssl.Fastly.net
GitHub静态资源IP assets-cdn.Github.com
  • host文件
Linux /etc/hosts
Windows C:\Windows\System32\drivers\etc\hosts
1
2
3
4
5
6
# 在结尾添加以下内容,注意前边地址要以查询到的为准
140.82.112.3 github.com
199.232.69.194 github.global.ssl.fastly.net
185.199.108.153 assets-cdn.github.com
185.199.110.153 assets-cdn.github.com
185.199.111.153 assets-cdn.github.com
  • 使用CMD命令刷新dns缓存
1
ipconfig /flushdns

5.2软件查询并修改hosts文件

【说明】此款软件可以查询延迟,操作相对容易,而且自己试了下,用的时候有效。

  • 软件截图
image-20220112163849973
  • 软件地址
1
https://www.dogfight360.com/blog/475/

【说明】软件来自:羽翼城个人博客

6.怎样使用Github

6.1注册Github账号

1
https://github.com/

进入网站后,点击sign up即可开始注册

image-20220112164049972

6.2新建仓库

  • 【头像左侧】→【+号】→【New repository
image-20220112164554671
  • 输入仓库相关信息,并创建即可
image-20220112165056498

6.3相关命令

【本地版本库与远程仓库相关命令】

  • 克隆
git-clone https://git-scm.com/docs/git-clone/en#_name
1
2
3
# 克隆相关操作
git clone <repository_url> # clone仓库
git clone <repository_url> another-repository-name # clone下来的仓库存储为其他名称
  • 推送与拉取
git-remote https://git-scm.com/docs/git-remote#_name
git-push https://git-scm.com/docs/git-push#_name
git-pull https://git-scm.com/docs/git-pull#_name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 添加本地仓库与远程仓库链接
# name为远程仓库地址设置一个别名,也可以为其他
# url为仓库地址
git remote add <name> <url>

git remote # 列出每个远程库的简短名字

git remote -v # 直接显示对应的克隆地址

git remote remove <name> # 删除本地仓库与远程仓库关联

git push -u <name> <branch name> # 将本地仓库文件上传到远程仓库分支

git pull <name> <远程分支名> # 从远程仓库更新本地仓库版本,远程分支与本地当前分支合并

git pull <name> <远程分支名>:<本地分支名> # 从远程仓库更新本地仓库版本,远程分支与本地当前分支合并

6.4实际操作

  HectorAndrea已经完成了大部分的功能,但是此时他要课程也多了起来,实验代码却都在实验室的电脑上,他们去实验室的时间少了许多。他们希望回到宿舍依然可以进行代码开发,所以他们想到了GitHub

  • 添加本地仓库与远程仓库的联系
1
2
git remote add origin git@github.com:qidaink/environment.git # 添加本地仓库与远程仓库链接 
git remote -v # 直接显示对应的克隆地址
image-20220115085456790
  • push程序到GitHub

  登陆自己的GitHub账号并进入相应的远程仓库地址,会发现master分支上的所有数据以及提交记录(与前边最后一次提交后的记录一致),全部都会显示在自己的远程仓库,要注意没有推送的分支是不会显示在GitHub远程仓库的,如果想要推送其他分支,在推送的时候写相应的分支即可。

1
2
git push -u origin master # 推送master分支
git push -u origin dev # 推送dev分支
image-20220115085735892
  • 克隆仓库

  回到宿舍后,他们需要clone一份程序到本地,怎么操作呢?

1
git clone git@github.com:qidaink/environment.git test
image-20220115091311253

  进入test文件夹,查看各项信息,会发现提交记录与文件都在,唯独缺少了dev分支,实际上该分支已经被下载下来了,我们可直接切换分支。

1
2
3
git mylog        # 查看提交记录
git branch # 查看分支
git checkout dev # 直接切换分支
image-20220115091550777

四、Git——beyond compare

  在Ubuntu环境下,有时候文件多的话,合并分支时产生的冲突可能也会很多,我们不能保证每一个文件都不漏,所以这款软件——beyond compare,会给我们带来很大的帮助。

4.1简介

  Beyond Compare是一套由Scooter Software推出的文件比较工具。主要用途是对比两个文件夹或者文件,并将差异以颜色标示。比较范围包括目录,文档内容等,可以用于git中合并分支的时候快速解决冲突。

4.2安装与配置

官方安装教程 Linux Installation Instructions
  • 下载安装包

  下载网址:

1
https://www.scootersoftware.com/download.php

  选择Linux中的64位Debian包下载,如果用以下命令下载速度特别慢的话,可以直接浏览器下载。

1
2
wget https://www.scootersoftware.com/bcompare-4.4.1.26165_amd64.deb
sudo apt update
  • 安装软件
1
2
3
# 进入deb所在文件夹,执行以下命令
cd ~
sudo apt install ./bcompare-4.4.1.26165_amd64.deb
  • 卸载软件
1
sudo apt remove bcompare
  • 安装密钥
1
2
3
4
# 进入相应文件夹
cd /usr/lib/beyondcompare/
# 执行以下命令
sudo sed -i "s/keexjEP3t4Mue23hrnuPtY4TdcsqNiJL-5174TsUdLmJSIXKfG2NGPwBL6vnRPddT7tH29qpkneX63DO9ECSPE9rzY1zhThHERg8lHM9IBFT+rVuiY823aQJuqzxCKIE1bcDqM4wgW01FH6oCBP1G4ub01xmb4BGSUG6ZrjxWHJyNLyIlGvOhoY2HAYzEtzYGwxFZn2JZ66o4RONkXjX0DF9EzsdUef3UAS+JQ+fCYReLawdjEe6tXCv88GKaaPKWxCeaUL9PejICQgRQOLGOZtZQkLgAelrOtehxz5ANOOqCaJgy2mJLQVLM5SJ9Dli909c5ybvEhVmIC0dc9dWH+/N9KmiLVlKMU7RJqnE+WXEEPI1SgglmfmLc1yVH7dqBb9ehOoKG9UE+HAE1YvH1XX2XVGeEqYUY-Tsk7YBTz0WpSpoYyPgx6Iki5KLtQ5G-aKP9eysnkuOAkrvHU8bLbGtZteGwJarev03PhfCioJL4OSqsmQGEvDbHFEbNl1qJtdwEriR+VNZts9vNNLk7UGfeNwIiqpxjk4Mn09nmSd8FhM4ifvcaIbNCRoMPGl6KU12iseSe+w+1kFsLhX+OhQM8WXcWV10cGqBzQE9OqOLUcg9n0krrR3KrohstS9smTwEx9olyLYppvC0p5i7dAx2deWvM1ZxKNs0BvcXGukR+/g" BCompare

  执行完毕之后,打开软件会有Trial Mode Error!弹窗,点击右下角的Enter Key,输入以下代码,出现Thanks for registering则表示注册成功。

1
2
3
--- BEGIN LICENSE KEY ---
GXN1eh9FbDiX1ACdd7XKMV7hL7x0ClBJLUJ-zFfKofjaj2yxE53xauIfkqZ8FoLpcZ0Ux6McTyNmODDSvSIHLYhg1QkTxjCeSCk6ARz0ABJcnUmd3dZYJNWFyJun14rmGByRnVPL49QH+Rs0kjRGKCB-cb8IT4Gf0Ue9WMQ1A6t31MO9jmjoYUeoUmbeAQSofvuK8GN1rLRv7WXfUJ0uyvYlGLqzq1ZoJAJDyo0Kdr4ThF-IXcv2cxVyWVW1SaMq8GFosDEGThnY7C-SgNXW30jqAOgiRjKKRX9RuNeDMFqgP2cuf0NMvyMrMScnM1ZyiAaJJtzbxqN5hZOMClUTE+++
--- END LICENSE KEY -----
image-20220115092850422

注册成功如下图所示

image-20220115092935369

4.3配置

1
2
3
4
5
6
# 查看bcompare软件位置
which bcompare
# 再进行以下配置local代表只在本地生效,全局生效可以改为global
git config --local merge.tool bc4
git config --local mergetool.path "/usr/bin/bcompare"
git config --local mergetool.keepBackup false

4.4使用方法

  • 启动软件

  先使用命令合并分支,若产生冲突,则使用以下命令启动软件:

1
git mergetool