前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【工具】Git 常用操作 - 备忘录

【工具】Git 常用操作 - 备忘录

作者头像
神仙朱
发布2020-03-10 11:15:03
4150
发布2020-03-10 11:15:03
举报

后面会把前端进阶的课程内容都总结一遍。有些都是很常见的知识,但是为了梳理自己的知识树,所以尽量模糊的地方都会记录

笔记列表在公众号右下角

Git 的内容已经很烂啦,我也把 Git 的原理相关的书看过研究过,但是奈何在项目中无非就用到那么几条命令,久而久之,其他命令就忘记了,当真正需要用的时候,又要搜索搜索学习学习,浪费太多时间。

网上资料很多,但是不一定适合自己,只好把用到概率大的命令统统详细记一遍,免得以后不时之需,也方便我复习,舒服~

本来只打算记录10条命令,学着学着发现其他命令也挺重要,然后就逐渐增加到 16 条命令,写了我 三个多星期,哎......不过也好,以后就不用为 git 花这么多心思了

这篇先记录这 16 条命令

1、git add

2、git commit

3、git push

4、git branch

5、git checkout

6、git merge

7、git log

8、git diff

9、git show

10、git status

11、git rebase

12、git pull

13、git stash

14、git reset

15、git reglog

16、git revert

0

基本概念

平时我们写的代码都是在工作区,没有 add 的修改 和 没有追踪的文件都会放在这里,以VScode 为例,工作区主要指这个地方

执行add命令后就是提交到了暂存区,就是 VSCode 的这个地方

再执行commit命令后就把代码提交到了本地版本库

最后再执行push命令把本地代码提交到远程版本库。

1

git add

有什么用?

将工作区内的文件提交到暂存区,添加文件进暂存区时,会根据文件的内容计算出HASH值

如果hash值存在,表示这个文件内容已经存在git仓库中,只需要更新索引

如果hash不存在,则在objects目录下新建一个blob文件,添加index索引。

? 有什么用法?

1

--- git add -a

提交所有变化,包括被修改,被删除,新增的文件

2

--- git add -u

提交被修改(modified),被删除(deleted)文件,不包括新文件(new)

3

--- git add .

提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件

2

git commit

有什么用?

将暂存区里的改动(git add 提交到暂存区的内容)给提交到本地的版本库,并生成一条提交记录,每条记录会配有一个40位哈希值的id

? 有什么用法?

1

--- git commit -m "你的注解"

提交一条记录,并为这条记录添加注解,就是解释这条记录做了什么改动

2

--- git commit -a -m "你的注解"

这条命令相当于省略了 git add -u 的操作,帮你先工作区中的被修改,被删除的文件,不包括新文件 提交到暂存区

然后再根据你的注释 生成提交记录,并提交到版本库

3

--- git commit -amend

这个命令就大有用处了,虽然我根本没用过,所以这才是我总结这篇文章的目的啊,你看多少盲点啊

大概有两个用处

1、修改上一条提交记录的注解

比如当你提交了记录,但是突然发现这个记录的注解写得不是很好,你想重写怎么办,用这个命令就对了

开始实操!

比如现在已经有一条记录了,如下

现在我们想修改这条记录的注解,直接输入命令,然后跳出这个界面,如下,然后在这红色标注的地方修改注释ok了

修改完成后,我们来看下记录,如下,可以看到已经被成功修改了

以为到这里就完了吗,没错,真的完了,但是要科普一下编辑页面的操作,没错,就是输入 --amend 命令后弹出的界面

我们来看下界面的简单操作

1、进入编辑状态:按 inert 键或者 按 i 键,进入编辑状态,不要瞎按了,进入界面的时候还是只读状态

2、编辑完成操作:按 ESC 键,退出编辑状态,按 :w 保存输入的内容,按 :q 退出界面 ,不过通常我们可以直接按 :wq 保存并退出

3、注意是 :w ,:q,:wq ,前面有一个冒号的啊,不要省略了

4、放弃修改:按三个键,:e! ,放弃所有修改,从上次保存文件开始编辑

2、给上一条已经提交的记录,额外新添加更多修改

比如我已经提交了一条记录,新增了一个文件 1.txt

但是后面发现我少提交了一个文件 2.txt,现在我要把 2.txt 添加到上一条记录上

开始操作!

看下当前已经提交的记录修改的内容,只提交了 1.txt

现在来把 2.txt 也合并到上一条记录中

1、git add 2.txt ,把 2.txt 也提交到暂存区

2、git commit --amend

跳出编辑界面,如果你不用修改注释的话,就直接按 :q 退出界面就合并成功了,如果你要编辑就参考上面的操作说明

然后再查看记录,如下,发现这条记录已经增加了 2.txt 啦,合并成功!!

3

git push

有什么用?

将 本地版本库的分支 推送到 远程主机上 指定的分支上

? 有什么用法?

1

--- git push origin master:master

一般形式为

git push <远程主机名> <本地分支名>:<远程分支名>

把 本地分支 master 推送到 远程主机 origin 的 master 分支上,origin 就是仓库地址

如果远程分支名和 本地分支名一样,通常我们可以省略掉远程分支名

像这样

git push origin master

2

--- git push -u origin master:master

为本地分支 指定推送的默认主机 和 远程分支

因为一般情况下,我们推送的时候,我们不可能写很长的命令

git push origin master:master

所以通常会指定默认主机和远程分支,这样我们直接 git push 就可以完成推送了

而且这里我们同样可以省略 远程分支名(如果和本地分支一样)

如果我们没有设置默认主机和分支,直接 git push,则会报错

?Tip

Git2.0之前,我们可以不用设置默认主机和远程分支,就可以直接使用 git push

但是在 Git2.0 之后,Git 修改了他们的默认 push 规则,把 push 的默认规则改成了 simple。表示,如果没有指定当前分支的 远程分支,那么就会报错

Git2.0之前,push 的默认规则是 matching,默认为本地分支指定了远程同名的分支,也就是说,本地的分支叫 master,远程的分支也是 master,那么这两者就会默认进行关联,建立追踪关系,本地 master 会自动推到远程的 master

而在 Git2.0 之后,虽然名字一样都是master,你也必须手动设置一遍,但是如果你手动设置的本地分支名字和 绑定过得远程分支名字不一样,同样会报错

比如你把本地的 test 和 远程的 master 分支 建立追踪关系,之后 你直接使用 git push 还是会报错,因为 Git2.0 设置的 push 规则是 simple,规定 本地和远程 分支名要一样

如果你实在想名字不一样,还想直接使用 git push,那么你可以把 push 规则设置为 upstream

代码语言:javascript
复制
git config --global push.default upstream

3

--- git push -f

忽略差异,强行推送本地分支,覆盖远程分支

一般团队合作的时候,因为同事已经先推送了他的代码,此时我再推送的话,就会先拉取他的代码,并且处理差异,但是这条命令可以让我们暴力推送,当然这么做是肯定不行的。。。

4

--- git push origin -d master

删除远程分支 ,这个master 就是远程分支的 master

5

--- git push --tag

推送本地打的标签。

通常我们使用 git push 的时候,并不会把本地的标签推送上去,所以我们需要额外去推送我们的标签

标签通常用来给 项目确定版本,所以会打上 v1.0.0 等标签,其实也就是给 commit 提交记录打上标签,该标签到上一个标签之前所有的提交属于一个版本,以此来区分代码版本

怎么打上标签呢?

代码语言:javascript
复制
git tag -a v2.0.0 -m "xxxx"

-a 后面接的是你要打的标签名,通常设置为版本号

-m 后面接的是这次标签的注释

4

git branch

有什么用?

管理本地分支和远程分支

? 有什么用法?

1

--- git branch <分支名字>

创建分支

你创建分支成功之后,你仍然处在之前的分支,并没有切换到新建的分支

2

--- git branch -a

查看所有分支,包括本地分支和远程分支

3

--- git branch -r

查看远程分支

4

--- git branch -d <分支名字>: 删除本地分支

如果你要同时删除多个分支,空格隔开分支名字就行了

3

--- git branch -D <分支名字>

强行删除

如果删除的时候分支被占用或者有冲突的时候,可以强行删除,只要你觉得没影响

3

--- git branch -d -r <远程分支名字>

删除远程分支

3

--- git branch -vv

查看本地分支对应的远程分支,也就是他们的追踪关系,如下图的 本地 b2 对应 远程 origin/rb2,本地 master 对应远程 origin/rmaster

如果你的本地分支和远程分支没有建立追踪关系,那么是无法显示远程分支的,如上图的 本地 b3 分支,没有和远程任何分支建立关系

3

--- git branch -m <old 分支名> <new 分支名>

给分支重命名

3

--- git branch --set-upstream-to=<远程主机>/<远程分支> <本地分支>

为 本地分支 绑定 默认远程主机 和 远程分支

如果你不写本地分支,那么就会默认为你当前所在的分支

比如你当前本地在 b2 分支上,你输入命令

git branch --set-upstream-to=origin/rb2

那么 本地分支 b2 就会远程分支 rb2 建立了追踪关系了

5

git checkout

有什么用?

用来操作分支和文件

? 有什么用法?

1

--- git checkout <分支名字>

切换分支,这个当然简单,比如,从 master 切换到 b2

但是我们要保证切换的分支都是存在的,否则就会报错

2

--- git checkout -b <分支名字>

创建分支并切换

之前我们创建的分支的时候,还要手动再切换过去有点麻烦,这里有个一条龙命令完成 创建+切换

3

--- git checkout <文件名字>

放弃工作区下指定文件的修改,就是放弃你还没有提交的修改。

注意是修改,如果是新增文件,不会被删除

3

--- git checkout .

放弃工作区下所有文件的修改,同上,放弃的是没有提交的修改

6

git merge

有什么用?

用来合并分支内容的,比如把 分支 B 合并到 分支 A 上

? 有什么用法?

1

--- git merge <分支名称>

用于合并分支

比如你想把 分支 A 合并到 主分支 master,你需要先切换到主分支 master,然后再合并分支 A

git checkout master

git merge A

默认合并模式是fast-forward,意思是 快进 ,相当于直接吞并分支,以上面为例

先说明,每个分支都有一个指针指向当前分支最新的提交,像这样

一个主分支 master 有一个指针,分支 A 有一个指针

当 master 要合并 分支 A ,使用 快进 模式,master 指针会直接移到 分支A 的指针处

相当于 master 分支拐到 分支A的方向,后面的提交就 顺着 分支A 原本的方向,而不是原本 master 的方向

虽然说是相当于 master 吞并了分支 A,但只是看着像而已,分支 A 仍然是独立的,你继续在 分支A 提交,会走到另一个方向,而不会和 master 互相影响

但是并不会都适合快进模式,比如当 master 已经有提交了,之前的虚拟提交 7 是真实存在的

这个时候肯定是无法直接吞并 分支 A 了,需要用到非快进模式,就是下一个指令会做的

也即是说,快进模式 只有在 分离出分支之后的 没有任何提交 的分支适用

举例就是

分支 B 分离 出 分支 C,然后在分支C 上工作,并且分离之后分支 B上没有任何提交,此时 分支B 再 合并 分支C ,就可以使用快进模式

2

--- git merge <分支名> --no-ff

ff 是 fast-forward 的意思,那么 no-ff 就是禁用快进的意思,就是不用快进模式进行合并

复制 合并分支 的最后一个提交的内容 ,跟 被合并分支 的所有内容 进行合并,形成一个新的提交

这么看肯定懵逼,必须要举例来说,就是

比如说 master 分离出了 分支 A,然后在 分支A 上进行了几次提交,然后切换回 master,要合并 分支A

使用 --no--ff 模式,就会复制master 的最后一个提交内容,然后和 分支A 所有内容进行合并,变成一个新的提交 ,提交放在 master 上

3

--- git merge <分支名> --squash

把 被合并分支上所有的内容都 添加到你 合并分支的 暂存区,等待你手动提交

? 继续举例

仍然是 master 要合并 分支 A,然后分支A 进行了几次提交,这几次提交的内容是 新增了几个文件

然后在 master 上 使用 squash 合并 分支A

然后,分支A 上的所有修改的内容,都会直接放到 master 的暂存区内(就是已经 add 而没有 commit)

然后需要你手动提交,然后 分支A 的所有内容 就 变成 master 的一个全新的提交

3

--- git merge --abort

回到文件 发生冲突之前的状态

比如你同事提交了代码,然后你拉取更新,发现有很多冲突,然后一一解决了,然后运行发现项目跑不了了,卧槽,怎么办,想直接恢复到没有拉取更新之前的状态,那么就用这个命令

比如一个项目中有一个 1.txt,是空白内容,你和同事同时拉下这个项目开始工作。

1、你在 1.txt 第一行 写下 神仙朱

2、同事在 1.txt 第一行写下 神仙猪崽,提交并上传到远程

3、然后你拉取他的代码,发生了冲突,你解决了,让 1.txt 都保留了 神仙朱 和神仙猪崽(只解决冲突,未提交),然后再运行项目发现,特么,跑不起来了!!

4、你想要恢复到发生冲突之前的内容,就是 1.txt 只有 神仙朱

5、那么你就用到这个命令 ,就可以满足你。

需要注意的是!!!

如果你解决完冲突之后,就马上提交了解决完冲突之后的文件,那么这个命令是无法帮你恢复的!!!!!!!

所以提醒我们的是在解决完冲突之后,不要猴急的马上提交,先运行项目观察一下先

7

git log

有什么用?

查看提交信息

git log 的用法有很多,但是都没有什么难理解的,就是参数多而已,这里就简略列举一些可能会用到的就好

? 有什么用法?

1

--- 过滤分类查找提交历史

1、git log --committer=<pattern>

过滤得到 某个人 提交的历史

2、git log --after=<date>

过滤得到某个时间之后的提交,时间的格式一般写成 这样 2020.02.17 02:46:01

并且这个时间是包含的

你过滤 2020.02.17 02:46:01 之后的提交,那么 2020.02.17 02:46:01 这个时间的提交也包含在内

3、git log --before=<date>

过滤得到某个时间之前的提交,时间格式如上,时间也是包含的

4、git log --after=<date> --before=<date>

相应的,你可以获取到某段时间内的提交

一定要注意这个 时间之前和之后,有时会有点懵逼

2020.02.17 02:46:01 之后的时间,肯定是比它晚比如是 2020.02.17 02:47:00

2020.02.17 03:00:00 之前的时间,肯定是比它早,比如是 2020.02.17 02:59:00

我之前把 after 和 before 的两个时间理解倒了,好半天筛选不出来

5、git log --grep=<pattern>

过滤得到 含有某些注释信息的 提交

比如你有三条提交,分别如下

git commit -m "1"

git commit -m "2"

git commit -m "3"

然后你想过滤得到注释信息含有 3的的提交

git log --grep=3

然后就可以了

当然了,这是支持正则的,你可以放上符合你要求的正则

6、git log --merges

过滤得到 那么属于合并 的提交

比如说,如果我们的使用 merge 合并的时候,使用 --no-off 模式,就会自动生成一个合并提交,像这样的带有这种注释的提交

然后我们想过滤得到这种提交,就可以使用这个命令

7、git shortlog

按照提交者,把提交分类

8、git log <filename>

查看单个文件的所有提交记录

2

--- 查看提交历史的细节多少

1、git log

这是我们最常规的用法,显示不多不少的提交信息,包含 commitId,时间,作者,提交信息等

2、git log --oneline

查看简略的提交信息,有时我们只是为了快速翻阅,对其他信息无所谓,所以想把提交信息一行显示就可以了

3、git log --stat

查看更详细的提交信息,有时想看每个提交修改了什么内容

4、git log --graph --oneline --decorate

显示仓库网络图,可以让我们可以直接地观察分支情况,想必我们之前肯定看到过这种图,五颜六色各种交叉的线

其实我们用这个命令就可以在本地查看这种线了

8

git diff

有什么用?

用于查看比较 文件 各个修改之间的差异

? 有什么用法?

1

--- git diff

工作区不为空,暂存区为空,比较 工作区和最后一个提交 的相同文件 的 差异

工作区不为空,暂存区不为空,比较 工作区和 暂存区的相同文件 的 差异

工作区为空,暂存区不为空,不比较

总的老说,必须有工作区,暂存区为不空就和暂存区比,为空就和最后一个提交比

diff 的使用作用都是一样的,区别只是在于 哪个谁跟谁比较而已

更重要的,我们需要了解一下 git diff 的输出内容

我们看到内容大概有五类内容,逐个来说明

第一行:diff --git a/master.txt b/master.txt

表示正在比较的是哪个文件,a 版本的 master.txt(改动前的内容),b 版本的 master.txt(改动后的内容)

第二行:index e19f8de..4af7630 100644

表示比较的两个版本的 哈希值,index 区域的 e19f8de 和 工作区中的 4af7630 。

index 表示 暂存区或者本地仓库

100644 表示对象的模式,其中 100 表示普通文件,644 表示权限‘’

第三、四行:--- a/master.txt +++ b/master.txt

--- a/master.txt 中的 "---" 表示变动前的版本

+++ b/master.txt中的"+++"表示变动后的版本

第五行:@@ -5,3 +5,5 @@

-5,3:减号,表示这是改动前的文件。5表示第五行,3表示连续3行,从第 5 行开始连续 3行(包括第5行)

+5,5:加号,表示这是改动后的文件。5表示第五行,5表示连续5行,从第5行开始连续 5行(包括第5行)

所以总的意思是,改动前的文件的 第 5 行开始连续 3行 和 改动后的文件 的 从第5行开始连续 5行 这部分内容有差异

其他:+测试diff 输出内容

+ 号,表示改动后的文件 新增的内容

- 号,表示改送后文件 删除的内容

2

--- git diff --cached

比较 暂存区 和 最后一个提交的相同文件 的 差异

同样的,你也可以使用 cached 这个参数让 暂存区 和 指定提交进行比较

git diff --cached commit-ID

3

--- git diff HEAD

比较 工作区 加上暂存区 这两个一起 和 最后一个提交的相同文件的差异

4

--- 其他

1、git diff commit-ID

你可以指定某个 commit 来 比较工作区 和 指定提交 之间 相同文件的 差异

2、git diff commit-ID-1 commit-ID-2

也可以比较两个 commit 的差异

3、git diff <branch-1> <branch-2>

也可以比较两个分支的差异

太多了,就列举这么多先,估计也不太用得到

9

git show

有什么用?

用于查看 各种类型对象的 相关信息,包括 blob 对象,tree 对象,tag 标签,commit 对象

但是说实话,我只用过show 来查看 commit 对象而已,其他对于我来说简直盲区.....

我忍着巨大的耐心去弄懂这个东西,真的很不容易

commit,tag,blob,tree 这四个东西其实是有联系的

简单来说

tag,就是 commit 的 别名,用于方便寻找。比如我们查看某个commit 通常要拿到它的 commitID,但是总归是很麻烦,所以就可以给 commit 一个 别名,这样我们可以直接通过查询别名来 查看 commit 信息

blob,表示项目中的文件,保存着 commit 时的文件的内容,比如说这个commit 我给文件新增了内容 "222",然后文件所有内容是 111 222,那么这个 commit 的 blob 存的就是 111 222,后面的 commit 修改的文件内容不会影响前面 commit的 blob

tree,表示项目目录结构,保存着 commit 时的 目录结构,同理,后面commit修改的文件目录不会影响前面commit的 tree,tree 下可能还会包含 blob 和 tree

commit ,就是提交,存储了很多信息,比如 tree,blob,作者,注释等等,每个commit 相当于把 当时的目录结构存在 tree,文件内容存在 blob,这样才能在回退的时候,完全恢复内容

? 有什么用法?

1

--- git show commit-ID

查看单个提交,并且更加详细些,包含了 diff 的输出内容,该diff内容是和上一个提交进行比较的

同理地,我们也可以使用git show 来查看 tag,tree,blob

对于 tag 可以直接使用别名,对于tree 和 blob 则是使用 哈希值,像 commitID 一样

查看tree 则是看到目录结构和文件

查看 blob 则是 看到文件内容

2

--- git show <commitID> --stat

显示简略的提交信息。

如果你不用看到 diff 的内容的话可以这么看就ok 了

10

git status

有什么用?

用于查看 工作目录和 暂存区的状态

? 有什么用法?

1

--- git status

如下,显示暂存区中修改(已经 add),工作区中修改(之前add 过,修改后没有add),工作区中没有追踪的文件

2

--- git status -s

简略显示工作区和暂存区的状态,一行搞定

红色表示在工作区(没有add),绿色表示在暂存区(已经add)

然后各种字母的意思是

D,删除

R,重命名

M,修改

A,新添加

U,更新但是没有合并

C,复制

??,没有追踪

11

git rebase

有什么用?

这个的作用太多了,可以用于合并分支,可以用于撤销提交

? 有什么用法?

这里主要记录是4个命令

1、git rebase

2、git rebase --onto

3、git rebase --abort

4、git rebase -i

1

--- git rebase <要合并的分支名>

重设分支基础点,作用跟 merge 一样,都是合并分支,只不过 rebase 可以把手脚做得很干净,不会留下合并的痕迹

是怎么不留痕迹呢?

相当于直接把 要合并的分支上的提交 搬到 目标分支 上

比如要把 分支 A 通过 rebase 合并到 master 上,相当于把 分支A 上的所有提交 直接搬到 master 上,而不是和 master 合并

搬过去的提交虽然是一毛一样的,连哈希值都一样,都是我测试修改 master 上的提交,并不会影响到 分支r 的提交,所以应该是复制了一份

这样搬过去的样子,像不像直接把 整个分支A 搬到 master 上?

所以这就是重设分支基础点啦,从 基础点3 变成基础点 7 了

这样 4 和 5 就好像是直接从 master 上提交的一样,完全看不出 合并的 痕迹 了

而如果 merge 则会留下痕迹,因为会生成一个 合并的新提交,而 rebase 则不会产生任何多余的 提交,就显得干净许多了

但是 rebase 到底是怎么操作的呢?

? 举个例子

比如要把 分支 A rebase 到 master 上,按步骤来

1、切换到 分支 A,git checkout A

2、开始rebase,git rebase master

3、这时可能会产生很多冲突,解决完毕 并且 add 之后,不使用 git commit 提交,因为此时 rebase 还没完成,所以使用 git rebase --continue 继续操作。每次继续可能又有新冲突,继续按上面来就可以了

4、rebase 完成,切换到 master,git checkout master

5、让 master指针 指向此时 master 分支最新的提交,git merge A

6、大功告成

2

--- git rebase --onto <合并到哪个分支> <起始提交ID> <结尾提交ID>

这个的作用和 直接 rebase 一样,但是 onto 的作用让我们可以指定合并的 起点和 终点

不像上条命令那样 直接合并整条分支,而是可以选其中几个提交来进行合并

需要注意的是,合并时不包括 起始提交,但是包括 结尾提交

? 举个例子

比如 分支A 上有提交 3,4,5,6 四个提交,我只要把 其中 4 和5 合并到 master 上

1、切换到分支 A 上,git checkout A

2、开始rebase,git rebase master commit-3-id commit-5-id(因为不包含起始提交,所以如果要 包含4,需要往前挪一个提交)

3、同样的,这里也可能会产生冲突,解决完毕 并且 add 之后,使用 git rebase --continue 继续 rebase 过程,还有冲突,则照样解决继续

4、rebase 完成,此时我们截取的部分提交成了 野生分支,我们需要给它一个名分安放它

git checkout -b new_b

5、同样的,master 没有指向最新的提交,所以我们需要让 master指针 指向此时 master 分支最新的提交,git merge new_b

6、大功告成,删除 new_b ,git branch -d new_b

3

--- git rebase --abort

如果在 rebase 的过程中,你后悔了,可以取消(有内鬼,终止交易), 然后 内容就会恢复到没有开始rebase之前一样

3

--- git rebase -i

这个命令可以做的事情有很多

1、修改以前的提交

2、删除很久以前的提交

3、多个 commit 合并为一个

....

可以做的还有很多,先列举这些

1修改以前的提交

之前我们知道可以使用 git commit --amend 来修改最新的提交,但是如果想修改的提交不是最新的,这个命令就没办法了,所以今天使用 git rebase -i

举例,比如我要修改 master 分支上的 倒数第三个提交

? 操作如下

1、切换到 master 分支,git checkout master

2、开始修改,指定到倒数第三个提交,git rebase -i HEAD~3(为什么是~3 后面有)

3、跳到一个新页面

上面的图中出现了三个提交,这里的提交是从旧到新的,就是说我要改的倒数第三个提交是 这个界面显示的第一个(对比下 git log 显示的提交)

4、因为我要修改,所以选择 edit 模式,把 pick 修改成 edit(记得按下 insert 进入编辑模式,完成之后按下 Esc,然后英文模式下按下三个键 :wq 保存)

5、跳出这个界面,提示 rebase 过程现在停在 倒数第三个 提交的位置

6、查看下 日志,真的是

7、项目中现在的内容是 倒数第三个提交的内容,现在你可以去项目中直接修改文件

我加了一行文字

8、然后就是 git add 和 git commit --amend,如果不用修改注释就直接 :q 退出,需要修改就 :wq 退出,关于这个界面的编辑按键操作 已经在 前面的 git commit 命令中已经有记录

9、继续 rebase 过程,之前开始 rebase 的时候,git 已经提示我们,如果完成了,就使用 git rebase --continue 继续完成 rebase 过程

如果执行命令发生冲突,便解决冲突,然后 add 之后,再使用 git rebase--continue 继续完成 rebase 过程,如果仍有冲突,也是一样解决。

直到最后提示成功

偏移符号

Git 中有两个偏移符号 ^ 和 ~ ,用于方便指定当前提交 后面的提交,往后数的意思

^ 和 ~ 作用 一样,但是用法稍有不同,都是跟在 commit 后面,这个commit 可以是哈希值,可以是指针(比如 master,HEAD)

1、^ 表示从指定地方往后数1个,^^ 表示往后数2个,反正就是 n个^ 就表示往后数 n 个

2、~ 则要跟上一个数字,~1 表示 从指定地方往后数1个,~2 表示往后数2个,,反正就是 ~n 就表示往后数 n 个

比如说,当前最新提交的id是 4850ba,往后数一个就是 4850ba^,往后数两个就是 4850ba~2 也可以是 4850ba^^

可以看个图了解下

看了偏移符号之后,就要清楚一下为什么修改倒数第三个提交 是 执行 HEAD~3 了

首先 HEAD~3 是 倒数第四个提交

如果你要修改倒数第三个,那我肯定是要把指针挪到倒数第四个

所以你要修改哪个commit,就要在 git rebase -i 中指定往后挪一个 commit

2删除很久以前的提交

和上面的操作是差不多的,只不过是选不同的模式而已,但是这个操作就简单很多了

现在我们要删除 master 分支倒数第三个提交

? 操作如下

1、切换到 master 分支,git checkout master

2、开始 rebase,git rebase -i HEAD~3,然后把 第一个 的模式改成 drop,或者可以直接把这一行删掉

同样,为什么是 HEAD~3 ,上面 <修改以前的提交> 有说到过,就是你要操作哪个commit,就要在命令中往后指定一个 commit

你要删除倒数第三个 commit,就是 HEAD~2,往后一个就是 HEAD~3

3、保存退出,如果有冲突,则像前面一样解决 add 然后 git rebase --continue 继续 reabse 过程

然后就会提示成功

查看日志,已经不见那个提交了

3多个 commit 合并为一个

看例子,我要把 master 上最新的三个提交合成一个

? 操作如下

1、切换到master,git checkout master

2、开始 rebase,git rebase -i HEAD~3,进入我们熟悉的编辑界面(这个界面的操作之前说过了,这里就不说了)

这里为什么是 HEAD~3,上面有说,可以回看

然后把后面两个提交模式修改成 s,也就是 squash 的简写

第一个不用改会报错,错误如下,意思大概是合成要保留一个最前面的提交

如果期间发生冲突,解决之后 ,add 之后使用 git rebase --continue,仍有冲突则照样解决然后跟前面一样就行

3、然后跳到另一个编辑的界面,含有这三个提交的信息

我们把这三个注释都删掉,然后改成一条注释,表明这条是我们合并的注释

4、编辑完成,:wq 保存退出,提示成功了

5、看下日志,已经合并成功了

rebase 总结

rebase 作用很大,但是也很麻烦,很难操作,要是一步弄错了就惨了,所以我在项目中也没有用过,但是肯定有必要学习的

其实还有很多用处,但是就先记住这几个就好了

12

git pull

有什么用?

拉取 远程主机的 指定分支 的内容,再和 本地指定分支进行合并

? 有什么用法?

1

--- git pull origin master:master

一般形式是

git pull <远程主机名> <本地分支名>:<远程分支名>

如果本地分支和远程分支一样,可以省略远程分支名和 冒号

git pull origin master

但是通常我们可以更加简写,git pull

只要我们为本地分支建立了默认主机和远程分支追踪关系的话

就像 git push -u 那样

记住,你给哪条分支做了绑定,才能在某条分支上简写命令。如果你只给 master 分支建立默认主机和默认远程分支,可以直接使用 git pull,但是切换到 分支 b1 直接使用 git pull ,仍然会报错,除非 b1 也做绑定

2

--- git pull --rebase

一般 git pull 默认是 git fetch + git merge

而 git pull --rebase = git fetch + git rebase

上面我们也说过 git merge 了,合并的时候可能会形成分叉,导致线路不好看

而 rebase 则会把拉取的提交直接放到 分支上,不会形成分叉,具体可以看上面 rebase 的指令

而使用 git pull --rebase 同样会有冲突,冲突解决完之后 只需要

1、git add 解决冲突的文件

2、git rebase --continue 来继续 rebase 过程

continue 之后又会有新的冲突,就继续解决冲突,然后按上面的过程来就好了

直到 rebase 过程完成

13

git stash

有什么用?

把改动临时存起来,需要的时候再提取

这个命令还是简单滴,而且能用到的机会很多,所以需要记住这个

? 有什么用法?

1

--- git stash

把 工作区和 暂存区的 内容都保存起来

看下图,本来 工作区和暂存区有内容的,输入 stash 之后,就被清空了,暂时保存到一个地方

并且我可以无限 stash,因为每次 stash 都会单独存一份,不会互相冲突

2

--- git stash save "注释"

通常我们临时报错的时候,最好还是给这次操作添加一个注释,说明正在做什么东西

3

--- git stash -u

上面临时保存的文件只包括已经追踪过的文件,新添加没有追踪过的文件是被排除在外的

不过加上 参数 -u 就可以解决

4

--- git stash list

查看 stash 的存放列表

列表是时间倒序排列的,最新的 保存放在最前面

5

--- git stash pop

我们已经知道怎么保存了,当然要知道怎么取出来了默认取出 stash 列表中最新的保存

但是需要注意的是,虽然 stash 可以把 暂存区和工作区的内容都保存起来

但是恢复的时候,会把所有内容都只恢复到工作区,就是原来在暂存区的现在也跑到工作区了,

6

--- git stash pop stash@{n}

因为存在列表,所以我们当然可以选择我们要恢复的 第几个 stash 了

n 从0 开始,第 0 个表示最新,依次递减

7

--- git stash drop stash@{n}

删除 stash,同上,我们可以选择删除第几个

14

git reset

有什么用?

reset 命令我们一般用来撤销 提交,而它是怎么撤销的呢?它是通过移动 HEAD 指针来撤销的,并且它会连带 分支指针一起移动

一般 HEAD 都是指向最新提交的,当前项目内容就是 HEAD指向的那个提交时 的内容

如果我们把 HEAD 往后挪一个提交,那么项目内容就会恢复到前一个提交时的内容

然后你再次提交的时候,就往另一条线走了,所以 提交5 就当成是撤销了

? 有什么用法?

1

--- git reset --mixed <撤销的提交往后挪一个>

撤销提交的同时,把 工作区,暂存区,以及撤销的那个提交 的内容,统统放进 工作区

并且,reset 默认的参数是 mixed,所以 加不加都一样

怎么指定我要撤销哪个提交?

这里命令中指定撤销哪个提交,不是撤销哪个就指定哪个,而是需要往后挪一个

比如你要撤销 最新的提交 6a75b5,那么命令中的参数就是

git reset --mixed 6a75b5^

因为你知道撤销提交是通过 移动 HEAD 指针实现的,你要撤销哪个提交,肯定是把 HEAD 指针挪到后面一位的位置

怎么撤销多个提交?

比如说你使用命令

git reset --mixed HEAD~3

那么 HEAD 指针就移动到 倒数第四个位置,那么 前面的所有 commit 都会被 撤销

? 命令解释示例如下

此时仓库已经存在两个提交,并且我添加一行数据放在暂存区,一行数据放在工作区

然后使用 reset 撤销最新的提交

2

--- git reset --hard <撤销的提交往后挪一个>

撤销提交的同时,清空工作区,清空暂存区,已经撤销的提交内容也不要,反正就是啥都不要

同样和上面例子一样

使用 reset --hard

3

--- git reset --soft <撤销的提交往后挪一个>

撤销提交的同时,保留工作区、暂存区不动, 把 撤销的提交的内容 放进暂存区

同样和上面例子一样

然后使用 reset --soft 撤销提交

15

git reflog

有什么用?

查看 本地仓库 的 指针的 移动记录。

主要是可以帮助你找到你删除过的分支,因为你删除分支其实只是删除指针,并没有把提交也删除了

所以只要找到 指针的移动记录,就能找到之前它指向的提交,这样就可以找回删除的分支了

但是注意的是,如果 commit 所在的分支没有任何指针,那么在一段时间在 Git 自动回收,所以如果你知道自己删错了,最好快点操作,不然就没戏了

你看下面这条分支就没有任何指针

但是 1、2、3 存在 另一条有指针的分支上,所以没事,而 4和 5 就变成野生的,过段时间就会被回收

? 有什么用法?

1

--- git reflog <分支指针>

帮你找到 指定的指针的移动记录。

如果我们不明确指定是什么指针,那么就会显示HEAD 的移动记录

? 举例

比如我新建了 分支 test,然后在上面新增两个提交,然后切换到 master,然后把 test 删除了

所以我们 可以看到 HEAD 移动记录是这样的,如下图

从 test 切换到 master 之后,test 被删除了,然后可以看到 HEAD 在 test 中最后一次的指向是下图中标红的提交

所以我们找到这个提交之后,就可以找到曾经 test 分支的所有提交啦

? 步骤如下

1、找到 HEAD 在 test 分支最后一次指向 commitID 是 5b38e41

2、切换到这个提交,git checkout 5b38e41

3、然后创建分支, git checkout -b test,此时就生成一个 test 指针指向了 commit 5b38e41

同样的,我们可以查看其他指针的动向,比如我的 分支 new_b

16

git revert

有什么用?

用于内容的撤销。

但是这个撤销跟之前的 rebase reset 不一样,这个指令不会动 你要撤销的提交一根寒毛

那它是怎么起到撤销的作用呢?

比如你要撤销的提交ID 是 6ab4e5

修改的内容是

1、增加了一行文字

2、删除了一个文件

然后你使用了 revert 指令撤销

然后就会生成一个新的提交,这个修改的内容跟你要撤销的 commit 完全相反,它的修改是

1、删除 那个 commit 增加的一行文字

2、恢复 那个 commit 删除的文件

也就是说,这个 revert 撤销,只是 新增一个commit用来 抹去 你要撤销的commit 的修改

? 有什么用法?

1

--- git revert <你要撤销的提交>

作用在上面已经讲完啦,就是 新增一个commit用来 抹去 你要撤销的commit 的修改

并且你要在命令中指定你撤销的提交

? 举例

来看下日志,我准备要撤销标红的这个提交

看下这个 commit 的修改内容,如下图,我就在末尾加了一个 2

按道理,如果我要revert 这个commit 的话,那么 生成的 commit 应该是删除 这个新增的 2

来试下,输入 git revert 4cd4b8a 之后,就跳到一个界面,此时 revert 已经生成了一个 提交,然后这是用于注释提交的界面,如果你不需要修改注释,就 :wq 退出

之后就成功增加了一条提交

我们看下这个新增的提交,如下图,没错,就是删除了 2

你是不是会觉得这个命令挺冗余的,明明我可以自己手动抹去内容然后新增提交啊,为什么还要 这个命令

但是如果你要撤销的内容很多的时候,自己手动一个个改肯定是麻烦不少

何不直接使用一个命令一步到位呢?

17

最后

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵, 如果有任何描述不当的地方,欢迎后台联系本人,领取红包

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神仙朱 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档