Git⾯试真题(10题)

发布于:2024-06-11 ⋅ 阅读:(45) ⋅ 点赞:(0)

目录

1. 说说你对版本管理的理解?常⽤的版本管理⼯具有哪些?

1.1. 是什么

1.2. 有哪些

1.2.1. 本地版本控制系统

1.2.2. 集中式版本控制系统

1.2.3. SVN

1.2.4. CVS

2. 说你对Git的理解?

2.1. 是什么

2.2. ⼯作原理

3. 说说Git常⽤的命令有哪些?

4. 说说Git 中 HEAD、⼯作树和索引之间的区别?

5. 说说 git 发⽣冲突的场景?如何解决?

6. 说说Git中 fork, clone,branch这三个概念,有什么区

7. 说说对git pull 和 git fetch 的理解?有什么区别?

8.说说你对git rebase 和 git merge的理解?区别?

9. 说说你对git reset 和 git revert 的理解?区别?9.1. 是什么

10. 说说你对git stash 的理解?应⽤场景?


1. 说说你对版本管理的理解?常⽤的版本管理⼯具有哪些?

1.1. 是什么

版本控制(Version control),是维护⼯程蓝图的标准作法,能追踪⼯程蓝图从诞⽣⼀直到定案的过 程。此外,版本控制也是⼀种软件⼯程技巧,借此能在软件开发的过程中,确保由不同⼈所编辑的同⼀ 程序⽂件都得到同步
透过⽂档控制,能记录任何⼯程项⽬内各个模块的改动历程,并为每次改动编上序号
⼀种简单的版本控制形式如下:赋给图的初版⼀个版本等级“A”。当做了第⼀次改变后,版本等级改 为“B”,以此类推 版本控制能提供项⽬的设计者,将设计恢复到之前任⼀状态的选择权。简⾔之,你的修改只要提到到版本控制系统,基本都可以找回,版本控制系统就像⼀台时光机器,可以
让你回到任何⼀个时间点

1.2. 有哪些

1 版本控制系统在当今的软件开发中,被认为是理所当然的配备⼯具之⼀,根据类别可以分成:
本地版本控制系统
集中式版本控制系统
分布式版本控制系统
1.2.1. 本地版本控制系统
结构如下图所示:
优点:
简单,很多系统中都有内置
适合管理⽂本,如系统配置
缺点:
其不⽀持远程操作,因此并不适合多⼈版本开发
1.2.2. 集中式版本控制系统
结构如下图所示:
优点:
适合多⼈团队协作开发
代码集中化管理
缺点:
单点故障
必须联⽹,⽆法单机⼯作
代表⼯具有 SVN CVS
1.2.3. SVN
TortoiseSVN 是⼀款⾮常易于使⽤的跨平台的 版本控制/版本控制/源代码控制软件
1.2.4. CVS
CVS 是版本控制系统,是源配置管理(SCM)的重要组成部分。使⽤它,您可以记录源⽂件和⽂档的历史记录。⽼牌的版本控制系统,它是基于客户端/服务器的⾏为使得其可容纳多⽤户,构成⽹络也很⽅便。这⼀特性使得 CVS 成为位于不同地点的⼈同时处理数据⽂件(特别是程序的源代码)时的⾸
1.2.4.1. 分布式版本控制系统
结构如下图:
优点:
适合多⼈团队协作开发
代码集中化管理
可以离线⼯作
每个计算机都是⼀个完整仓库
分布式版本管理系统每个计算机都有⼀个完整的仓库,可本地提交,可以做到离线⼯作,则不⽤像集中管理那样因为断⽹情况⽽⽆法⼯作代表⼯具为 Git 、 HG:
Git 是⽬前世界上最先进的分布式版本控制系统,旨在快速⾼效地处理从⼩型到⼤型项⽬的所有事务
特性:易于学习,占⽤内存⼩,具有闪电般快速的性能
使⽤ Git Gitlab 搭建版本控制环境是现在互联⽹公司最流⾏的版本控制⽅式
Mercurial 是⼀个免费的分布式源代码管理⼯具。它可以有效地处理任何规模的项⽬,并提供简单直 观的界⾯
Mercurial 是⼀种轻量级分布式版本控制系统,采⽤ Python 语⾔实现,易于学习和使⽤,扩展性
强 版本控制系统的优点如下:
记录⽂件所有历史变化,这是版本控制系统的基本能⼒
随时恢复到任意时间点,历史记录功能使我们不怕改错代码了
⽀持多功能并⾏开发,通常版本控制系统都⽀持分⽀,保证了并⾏开发的可⾏
多⼈协作并⾏开发,对于多⼈协作项⽬,⽀持多⼈协作开发的版本管理将事半功倍

2. 说你对Git的理解?

2.1. 是什么

git,是⼀个分布式版本控制软件,最初⽬的是为更好地管理 Linux 内核开发⽽设计
分布式版本控制系统的客户端并不只提取最新版本的⽂件快照,⽽是把代码仓库完整地镜像下来。这么 ⼀来,任何⼀处协同⼯作⽤的服务器发⽣故障,事后都可以⽤任何⼀个镜像出来的本地仓库恢复 项⽬开始,只有⼀个原始版仓库,别的机器可以 clone 这个原始版本库,那么所有 clone 的机器, 它们的版本库其实都是⼀样的,并没有主次之分 所以在实现团队协作的时候,只要有⼀台电脑充当服务器的⻆⾊,其他每个⼈都从这个“服务器”仓库 cl
one ⼀份到⾃⼰的电脑上,并且各⾃把各⾃的提交推送到服务器仓库⾥,也从服务器仓库中拉取别⼈的 提交 github 实际就可以充当这个服务器⻆⾊,其是⼀个开源协作社区,提供 Git 仓库托管服务,既可以 让别⼈参与你的开源项⽬,也可以参与别⼈的开源项⽬

2.2. ⼯作原理

当我们通过 git init 创建或者 git clone ⼀个项⽬的时候,项⽬⽬录会隐藏⼀个 .git ⼦⽬录,
其作⽤是⽤来跟踪管理版本库的
Git 中所有数据在存储前都计算校验和,然后以校验和来引⽤,所以在我们修改或者删除⽂件的时
候, git 能够知道
Git ⽤以计算校验和的机制叫做 SHA-1 散列(hash,哈希), 这是⼀个由 40 个⼗六进制字符(0-
9 和 a-f)组成字符串,基于 Git 中⽂件的内容或⽬录结构计算出来,如下:
当我们修改⽂件的时候, git 就会修改⽂件的状态,可以通过 git status 进⾏查询,状态情况如
下:
已修改(modified):表示修改了⽂件,但还没保存到数据库中。
已暂存(staged):表示对⼀个已修改⽂件的当前版本做了标记,使之包含在下次提交的快照中。
已提交(committed):表示数据已经安全的保存在本地数据库中。
⽂件状态对应的,不同状态的⽂件在 Git 中处于不同的⼯作区域,主要分成了四部分:
⼯作区:相当于本地写代码的区域,如 git clone ⼀个项⽬到本地,相当于本地克隆了远程仓库项⽬
的⼀个副本
暂存区:暂存区是⼀个⽂件,保存了下次将提交的⽂件列表信息,⼀般在 Git 仓库⽬录中
本地仓库:提交更新,找到暂存区域的⽂件,将快照永久性存储到 Git 本地仓库
远程仓库:远程的仓库,如 github
LaTeX
复制代码 2.3. 命令
从上图可以看到, git ⽇常简单的使⽤就只有上图6个命令:
add
commit
push
pull
clone
checkout

3. 说说Git常⽤的命令有哪些?

3.1. 前⾔
git 的操作可以通过命令的形式如执⾏,⽇常使⽤就如下图6个命令即可
9 实际上,如果想要熟练使⽤,超过60多个命令需要了解,下⾯则介绍下常⻅的的 git 命令
3.2. 有哪些
3.3. 配置
Git ⾃带⼀个 git config 的⼯具来帮助设置控制 Git 外观和⾏为的配置变量,在我们安装完
git 之后,第⼀件事就是设置你的⽤户名和邮件地址
后续每⼀个提交都会使⽤这些信息,它们会写⼊到你的每⼀次提交中,不可更改
设置提交代码时的⽤户信息命令如下:
git config [--global] user.name "[name]"
git config [--global] user.email "[email address]"
3.3.1. 启动
⼀个 git 项⽬的初始有两个途径,分别是:
git init [project-name]:创建或在当前⽬录初始化⼀个git代码库
git clone url:下载⼀个项⽬和它的整个代码历史
3.3.2. ⽇常基本操作
在⽇常⼯作中,代码常⽤的基本操作如下:
git init 初始化仓库,默认为 master 分⽀
git add . 提交全部⽂件修改到缓存区
git add <具体某个⽂件路径+全名> 提交某些⽂件到缓存区
git diff 查看当前代码 add后,会 add 哪些内容
git diff --staged查看现在 commit 提交后,会提交哪些内容
git status 查看当前分⽀状态
git pull <远程仓库名> <远程分⽀名> 拉取远程仓库的分⽀与本地当前分⽀合并
git pull <远程仓库名> <远程分⽀名>:<本地分⽀名> 拉取远程仓库的分⽀与本地某个分⽀合并
git commit -m "<注释>" 提交代码到本地仓库,并写提交注释
git commit -v 提交时显示所有diff信息
10 git commit --amend [file1] [file2] 重做上⼀次commit,并包括指定⽂件的新变化
关于提交信息的格式,可以遵循以下的规则:
feat: 新特性,添加功能
fix: 修改 bug
refactor: 代码重构
docs: ⽂档修改
style: 代码格式修改, 注意不是 css 修改
test: 测试⽤例修改
chore: 其他修改, ⽐如构建流程, 依赖管理
3.3.3. 分⽀操作
git branch 查看本地所有分⽀
git branch -r 查看远程所有分⽀
git branch -a 查看本地和远程所有分⽀
git merge <分⽀名> 合并分⽀
git merge --abort 合并分⽀出现冲突时,取消合并,⼀切回到合并前的状态
git branch <新分⽀名> 基于当前分⽀,新建⼀个分⽀
git checkout --orphan <新分⽀名> 新建⼀个空分⽀(会保留之前分⽀的所有⽂件)
git branch -D <分⽀名> 删除本地某个分⽀
git push <远程库名> :<分⽀名> 删除远程某个分⽀
git branch <新分⽀名称> <提交ID> 从提交历史恢复某个删掉的某个分⽀
git branch -m <原分⽀名> <新分⽀名> 分⽀更名
git checkout <分⽀名> 切换到本地某个分⽀
git checkout <远程库名>/<分⽀名> 切换到线上某个分⽀
git checkout -b <新分⽀名> 把基于当前分⽀新建分⽀,并切换为这个分⽀
3.3.4. 远程同步
远程操作常⻅的命令:
git fetch [remote] 下载远程仓库的所有变动
git remote -v 显示所有远程仓库
git pull [remote] [branch] 拉取远程仓库的分⽀与本地当前分⽀合并
11 git fetch 获取线上最新版信息记录,不合并
git push [remote] [branch] 上传本地指定分⽀到远程仓库
git push [remote] --force 强⾏推送当前分⽀到远程仓库,即使有冲突
git push [remote] --all 推送所有分⽀到远程仓库
3.3.5. 撤销
git checkout [file] 恢复暂存区的指定⽂件到⼯作区
git checkout [commit] [file] 恢复某个commit的指定⽂件到暂存区和⼯作区
git checkout . 恢复暂存区的所有⽂件到⼯作区
git reset [commit] 重置当前分⽀的指针为指定commit,同时重置暂存区,但⼯作区不变
git reset --hard 重置暂存区与⼯作区,与上⼀次commit保持⼀致
git reset [file] 重置暂存区的指定⽂件,与上⼀次commit保持⼀致,但⼯作区不变
git revert [commit] 后者的所有变化都将被前者抵消,并且应⽤到当前分⽀
reset :真实硬性回滚,⽬标版本后⾯的提交记录全部丢失了
revert :同样回滚,这个回滚操作相当于⼀个提价,⽬标版本后⾯的提交记录也全部都有
3.3.6. 存储操作
你正在进⾏项⽬中某⼀部分的⼯作,⾥⾯的东⻄处于⼀个⽐较杂乱的状态,⽽你想转到其他分⽀上进⾏
⼀些⼯作,但⼜不想提交这些杂乱的代码,这时候可以将代码进⾏存储
git stash 暂时将未提交的变化移除
git stash pop 取出储藏中最后存⼊的⼯作状态进⾏恢复,会删除储藏
git stash list 查看所有储藏中的⼯作
git stash apply <储藏的名称> 取出储藏中对应的⼯作状态进⾏恢复,不会删除储藏
git stash clear 清空所有储藏中的⼯作
git stash drop <储藏的名称> 删除对应的某个储藏
3.4. 总结
git 常⽤命令速查表如下所示:

4. 说说Git 中 HEAD、⼯作树和索引之间的区别?

4.1. HEAD
13 14
git 中,可以存在很多分⽀,其本质上是⼀个指向 commit 对象的可变指针,⽽ Head 是⼀个特
别的指针,是⼀个指向你正在⼯作中的本地分⽀的指针
简单来讲,就是你现在在哪⼉,HEAD 就指向哪⼉
例如当前我们处于 master 分⽀,所以 HEAD 这个指针指向了 master 分⽀指针
然后通过调⽤ git checkout test 切换到 test 分⽀,那么
HEAD 则指向 test 分⽀,如下图: 15
但我们在 test 分⽀再⼀次 commit 信息的时候, HEAD 指针仍然指向了 test 分⽀指针,⽽ tes
t 分⽀指针已经指向了最新创建的提交,如下图:
这个 HEAD 存储的位置就在 .git/HEAD ⽬录中,查看信息可以看到
HEAD 指向了另⼀个⽂件 16
这个⽂件的内容是⼀串哈希码,⽽这个哈希码正是 master 分⽀上最新的提交所对应的哈希码
所以,当我们切换分⽀的时候, HEAD 指针通常指向我们所在的分⽀,当我们在某个分⽀上创建新的提
交时,分⽀指针总是会指向当前分⽀的最新提交
所以,HEAD指针 ——–> 分⽀指针 ——–> 最新提交
Git 管理下,⼤家实际操作的⽬录被称为⼯作树,也就是⼯作区域
在数据库和⼯作树之间有索引,索引是为了向数据库提交作准备的区域,也被称为暂存区域
Git 在执⾏提交的时候,不是直接将⼯作树的状态保存到数据库,⽽是将设置在中间索引区域的状态
保存到数据库
因此,要提交⽂件,⾸先需要把⽂件加⼊到索引区域中。
所以,凭借中间的索引,可以避免⼯作树中不必要的⽂件提交,还可以将⽂件修改内容的⼀部分加⼊索
引区域并提交
4.2. ⼯作树和索引
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
7406a10efcc169bbab17827aeda189aa20376f7f
1
2
3
4
5
Plain Text
复制代码 17
从所在的位置来看:
HEAD 指针通常指向我们所在的分⽀,当我们在某个分⽀上创建新的提交时,分⽀指针总是会指向
当前分⽀的最新提交
⼯作树是查看和编辑的(源)⽂件的实际内容
索引是放置你想要提交给 git仓库⽂件的地⽅,如⼯作树的代码通过 git add 则添加到 git 索引中,
通过git commit 则将索引区域的⽂件提交到 git 仓库中
⼀般情况下,出现分⽀的场景有如下:
多个分⽀代码合并到⼀个分⽀时
多个分⽀向同⼀个远端分⽀推送
具体情况就是,多个分⽀修改了同⼀个⽂件(任何地⽅)或者多个分⽀修改了同⼀个⽂件的名称
如果两个分⽀中分别修改了不同⽂件中的部分,是不会产⽣冲突,直接合并即可
应⽤在命令中,就是 push pull stash
rebase 等命令下都有可能产⽣冲突情况,从本质
上来讲,都是 merge patch (应⽤补丁)时产⽣冲突
4.3. 区别

5. 说说 git 发⽣冲突的场景?如何解决?

5.1. 是什么
18
在本地主分值 master 创建⼀个 a.txt ⽂件,⽂件起始位置写上 master commit ,如下:
然后提交到仓库:
git add a.txt
git commit -m 'master first commit'
创建⼀个新的分⽀ featurel1 分⽀,并进⾏切换,如下:
然后修改 a.txt ⽂件⾸⾏⽂字为 featurel commit ,然后添加到暂存区,并开始进⾏提交到仓
库:
git add a.txt
git commit -m 'featurel first change'
然后通过 git checkout master 切换到主分⽀,通过 git merge 进⾏合并,发现不会冲突
此时 a.txt ⽂件的内容变成 featurel commit ,没有出现冲突情况,这是因为 git 在内部发⽣
了快速合并
如果此时切换到 featurel 分⽀,将⽂件的内容修改成 featrue second commit ,然后提交到本
地仓库
然后切换到主分⽀,如果此时在 a.txt ⽂件再次修改,修改成 mastet second commit ,然后再
次提交到本地仓库
此时, master 分⽀和 feature1 分⽀各⾃都分别有新的提交,变成了下图所示:
5.2. 分析
如果当前分⽀的每⼀个提交(commit)都已经存在另⼀个分⽀⾥了,git 就会执⾏⼀个“快速向前”(fast
forward)操作
git 不创建任何新的提交(commit),只是将当前分⽀指向合并进来的分⽀
git checkout -b featurel1
1
Plain Text
复制代码 这种情况下,⽆法执⾏快速合并,只能试图把各⾃的修改合并起来,但这种合并就可能会有冲突
现在通过 git merge featurel 进⾏分⽀合并,如下所示:
从冲突信息可以看到, a.txt 发⽣冲突,必须⼿动解决冲突之后再提交
git status 同样可以告知我们冲突的⽂件:
打开 a.txt ⽂件,可以看到如下内容:
19 20
git <<<<<<< ======= >>>>>>> 标记出不同分⽀的内容:
<<<<<<< 和 ======= 之间的区域就是当前更改的内容
======= 和 >>>>>>> 之间的区域就是传⼊进来更改的内容
现在要做的事情就是将冲突的内容进⾏更改,对每个⽂件使⽤ git add 命令来将其标记为冲突已解
决。 ⼀旦暂存这些原本有冲突的⽂件, Git 就会将它们标记为冲突已解决然后再提交:
git add a.txt
git commit -m "conflict fixed"
此时 master 分⽀和 feature1 分⽀变成了下图所示:
使⽤ git log 命令可以看到合并的信息:
21
Git ⽆法⾃动合并分⽀时,就必须⾸先解决冲突,解决冲突后,再提交,合并完成
解决冲突是把 Git 合并失败的⽂件⼿动编辑为我们希望的内容,再提交
fork ,英语翻译过来就是叉⼦,动词形式则是分叉,如下图,从左到右,⼀条直线变成多条直线
转到 git 仓库中, fork 则可以代表分叉、克隆 出⼀个(仓库的)新拷⻉
5.3. 总结

6. 说说Git中 fork, clone,branch这三个概念,有什么区

别?
6.1. 是什么
6.1.1. fork 包含了原来的仓库(即upstream repository,上游仓库)所有内容,如分⽀、Tag、提交
如果想将你的修改合并到原项⽬中时,可以通过的 Pull Request 把你的提交贡献回 原仓库
6.1.2. clone
clone ,译为克隆,它的作⽤是将⽂件从远程代码仓下载到本地,从⽽形成⼀个本地代码仓
执⾏ clone 命令后,会在当前⽬录下创建⼀个名为 xxx 的⽬录,并在这个⽬录下初始化⼀个 .git
⽂件夹,然后从中读取最新版本的⽂件的拷⻉
默认配置下远程 Git 仓库中的每⼀个⽂件的每⼀个版本都将被拉取下来
6.1.3. branch
branch ,译为分⽀,其作⽤简单⽽⾔就是开启另⼀个分⽀, 使⽤分⽀意味着你可以把你的⼯作从开
发主线上分离开来,以免影响开发主线
Git 处理分⽀的⽅式⼗分轻量,创建新分⽀这⼀操作⼏乎能在瞬间完成,并且在不同分⽀之间的切换
操作也是⼀样便捷
在我们开发中,默认只有⼀条 master 分⽀,如下图所示:
22 通过 git branch 可以创建⼀个分⽀,但并不会⾃动切换到新分⽀中去
通过 git checkout 可以切换到另⼀个 testing 分⽀
23 24
当你在 github 发现感兴趣开源项⽬的时候,可以通过点击 github 仓库中右上⻆ fork 标识的按
钮,如下图:
点击这个操作后会将这个仓库的⽂件、提交历史、issues和其余东⻄的仓库复制到⾃⼰的 github 仓库
中,⽽你本地仓库是不会存在任何更改
然后你就可以通过 git clone 对你这个复制的远程仓库进⾏克隆
6.2. 如何使⽤
6.2.1. fork 25
后续更改任何东⻄都可以在本地完成,如 git add git commit ⼀系列的操作,然后通
push 命令推到⾃⼰的远程仓库
如果希望对⽅接受你的修改,可以通过发送 pull requests 给对⽅,如果对⽅接受。则会将你的修
改内容更新到仓库中
整体流程如下图
github 中,开源项⽬右侧存在 code 按钮,点击后则会显示开源项⽬ url 信息,如下图所示:
6.2.2. clone 通过 git clone xxx 则能完成远程项⽬的下载
6.2.3. branch
可通过 git branch 进⾏查看当前的分⽀状态,
如果给了 --list ,或者没有⾮选项参数,现有的分⽀将被列出;当前的分⽀将以绿⾊突出显示,并标
有星号
以及通过 git branch 创建⼀个新的分⽀出来
6.3. 区别
其三者区别如下:
fork 只能对代码仓进⾏操作,且 fork 不属于 git 的命令,通常⽤于代码仓托管平台的⼀种“操作”
clone 是 git 的⼀种命令,它的作⽤是将⽂件从远程代码仓下载到本地,从⽽形成⼀个本地代码仓
branch 特征与 fork 很类似,fork 得到的是⼀个新的、⾃⼰的代码仓,⽽ branch 得到的是⼀个代
码仓的⼀个新分⽀

7. 说说对git pull 和 git fetch 的理解?有什么区别?

26 27
先回顾两个命令的定义
git fetch 命令⽤于从另⼀个存储库下载对象和引⽤
git pull 命令⽤于从另⼀个存储库或本地分⽀获取并集成(整合)
再来看⼀次 git 的⼯作流程图,如下所示:
可以看到, git fetch 是将远程主机的最新内容拉到本地,⽤户在检查了以后决定是否合并到⼯作本
机分⽀中
git pull 则是将远程主机的最新内容拉下来后直接合并,即: git pull = git fetch + gi
t merge ,这样可能会产⽣冲突,需要⼿动解决
在我们本地的 git ⽂件中对应也存储了 git 本地仓库分⽀的 commit ID 和 跟踪的远程分⽀的 co
mmit ID ,对应⽂件如下:
.git/refs/head/[本地分⽀]
.git/refs/remotes/[正在跟踪的分⽀]
使⽤ git fetch 更新代码,本地的库中 master commitID 不变
7.1. 是什么
28
但是与 git 上⾯关联的那个 orign/master commit ID 发⽣改变
这时候本地相当于存储了两个代码的版本号,我们还要通过 merge 去合并这两个不同的代码版本
也就是 fetch 的时候本地的 master 没有变化,但是与远程仓关联的那个版本号被更新了,接下来就
是在本地 merge 合并这两个版本号的代码
相⽐之下,使⽤ git pull 就更加简单粗暴,会将本地的代码更新⾄远程仓库⾥⾯最新的代码版本,
如下图: 29
⼀般远端仓库⾥有新的内容更新,当我们需要把新内容下载的时候,就使⽤到 git pull 或者 git f
etch 命令
⽤法如下:
例如从远程的 origin 仓库的 master 分⽀下载代码到本地并新建⼀个 temp 分⽀
如果上述没有冒号,则表示将远程 origin 仓库的 master 分⽀拉取下来到本地当前分⽀
这⾥ git fetch 不会进⾏合并,执⾏后需要⼿动执⾏ git merge 合并,如下:
7.2. ⽤法
7.2.1. fetch
git fetch < 远程主机名 > < 远程分⽀名 >:< 本地分⽀名 >
1
Plain Text
复制代码
git fetch origin master:temp
1
Plain Text
复制代码 30
两者的⽤法⼗分相似, pull ⽤法如下:
例如将远程主机 origin master 分⽀拉取过来,与本地的 branchtest 分⽀合并,命令如下:
同样如果上述没有冒号,则表示将远程 origin 仓库的 master 分⽀拉取下来与本地当前分⽀合并
相同点:
在作⽤上他们的功能是⼤致相同的,都是起到了更新代码的作⽤
不同点:
git pull是相当于从远程仓库获取最新版本,然后再与本地分⽀merge,即git pull = git fetch + git
merge
相⽐起来,git fetch 更安全也更符合实际要求,在 merge 前,我们可以查看更新情况,根据实际情
况再决定是否合并
7.2.2. pull
7.3. 区别
8. 说说你对git rebase 和 git merge的理解?区别?
git merge temp
1
Plain Text
复制代码
git pull < 远程主机名 > < 远程分⽀名 >:< 本地分⽀名 >
1
Plain Text
复制代码
git pull origin master:branchtest
1
Plain Text
复制代码 31
在使⽤ git 进⾏版本管理的项⽬中,当完成⼀个特性的开发并将其合并到 master 分⽀时,会有
两种⽅式:
git merge
git rebase
git rebase git merge 都有相同的作⽤,都是将⼀个分⽀的提交合并到另⼀分⽀上,但是在
原理上却不相同
⽤法上两者也⼗分的简单:
将当前分⽀合并到指定分⽀,命令⽤法如下:
将当前分⽀移植到指定分⽀或指定 commit 之上,⽤法如下:

8.说说你对git rebase 和 git merge的理解?区别?

8.1. 是什么
8.1.1. git merge
8.1.2. git rebase
git merge xxx
1
Plain Text
复制代码
git rebase -i <commit>
1
Plain Text
复制代码 32
常⻅的参数有 --continue ,⽤于解决冲突之后,继续执⾏ rebase
通过 git merge 将当前分⽀与 xxx 分⽀合并,产⽣的新的 commit 对象有两个⽗节点
如果“指定分⽀”本身是当前分⽀的⼀个直接⼦节点,则会产⽣快照合并
举个例⼦, bugfix 分⽀是从 master 分⽀分叉出来的,如下所示:
合并 bugfix 分⽀到 master 分⽀时,如果 master 分⽀的状态没有被更改过,即 bugfix 分⽀
的历史记录包含 master 分⽀所有的历史记录
所以通过把 master 分⽀的位置移动到 bugfix 的最新分⽀上,就完成合并
如果 master 分⽀的历史记录在创建 bugfix 分⽀后⼜有新的提交,如下情况:
这时候使⽤ git merge 的时候,会⽣成⼀个新的提交,并且 master 分⽀的 HEAD 会移动到新的分
⽀上,如下:
8.2. ⼆、分析
8.2.1. git merge
git rebase --continue
1
Plain Text
复制代码 33
从上⾯可以看到,会把两个分⽀的最新快照以及⼆者最近的共同祖先进⾏三⽅合并,合并的结果是⽣成
⼀个新的快照
同样, master 分⽀的历史记录在创建 bugfix 分⽀后⼜有新的提交,如下情况:
通过 git rebase ,会变成如下情况:
在移交过程中,如果发⽣冲突,需要修改各⾃的冲突,如下:
8.2.2. git rebase 34
rebase 之后, master HEAD 位置不变。因此,要合并 master 分⽀和 bugfix 分⽀
从上⾯可以看到, rebase 会找到不同的分⽀的最近共同祖先,如上图的
B
然后对⽐当前分⽀相对于该祖先的历次提交,提取相应的修改并存为临时⽂件(⽼的提交 X
Y
也没
有被销毁,只是简单地不能再被访问或者使⽤)
然后将当前分⽀指向⽬标最新位置 D , 然后将之前另存为临时⽂件的修改依序应⽤
从上⾯可以看到, merge rebasea 都是合并历史记录,但是各⾃特性不同:
通过 merge 合并分⽀会新增⼀个 merge commit ,然后将两个分⽀的历史联系起来
其实是⼀种⾮破坏性的操作,对现有分⽀不会以任何⽅式被更改,但是会导致历史记录相对复杂
rebase 会将整个分⽀移动到另⼀个分⽀上,有效地整合了所有分⽀上的提交
主要的好处是历史记录更加清晰,是在原有提交的基础上将差异内容反映进去,消除了 git merge
需的不必要的合并提交
8.3. 区别
8.3.1. merge
8.3.2. rebase

9. 说说你对git reset 和 git revert 的理解?区别?9.1. 是什么

9.1.1. git reset
reset ⽤于回退版本,可以遗弃不再使⽤的提交
执⾏遗弃时,需要根据影响的范围⽽指定不同的参数,可以指定是否复原索引或⼯作树内容
35 9.1.2. git revert
在当前提交后⾯,新增⼀次提交,抵消掉上⼀次提交导致的所有变化,不会改变过去的历史,主要是⽤
于安全地取消过去发布的提交
9.2. 如何⽤
9.2.1. git reset
36 37
当没有指定 ID 的时候,默认使⽤ HEAD ,如果指定
ID
,那么就是基于指向
ID
去变动暂存区或⼯
作区的内容
⽇志 ID 可以通过查询,可以 git log 进⾏查询,如下:
常⻅命令如下
--mixed(默认):默认的时候,只有暂存区变化
--hard参数:如果使⽤ --hard 参数,那么⼯作区也会变化
--soft:如果使⽤ --soft 参数,那么暂存区和⼯作区都不会变化
// 没有指定 ID, 暂存区的内容会被当前 ID 版本号的内容覆盖,⼯作区不变
git reset
// 指定 ID ,暂存区的内容会被指定 ID 版本号的内容覆盖,⼯作区不变
git reset <ID>
1
2
3
4
5
Plain Text
复制代码
commit a7700083ace1204ccdff9f71631fb34c9913f7c5 (HEAD -> master)
Author: linguanghui <linguanghui@baidu.com>
Date: Tue Aug 17 22:34:40 2021 +0800
second commit
commit e31118663ce66717edd8a179688a7f3dde5a9393
Author: linguanghui <linguanghui@baidu.com>
Date: Tue Aug 17 22:20:01 2021 +0800
first commit
1
2
3
4
5
6
7
8
9
10
11
Plain Text
复制代码 38
git reset ⽤法基本⼀致, git revert 撤销某次操作,此次操作之前和之后的
commit
history 都会保留,并且把这次撤销,作为⼀次最新的提交,如下:
如果撤销前⼀个版本,可以通过如下命令:
撤销前前⼀次,如下:
9.2.2. git revert
git revert <commit_id>
1
Plain Text
复制代码
git revert HEAD
1
Plain Text
复制代码
git revert HEAD^
1
Plain Text
复制代码 9.3. 区别
撤销(revert)被设计为撤销公开的提交(⽐如已经push)的安全⽅式, git reset 被设计为重设本
地更改
因为两个命令的⽬的不同,它们的实现也不⼀样:重设完全地移除了⼀堆更改,⽽撤销保留了原来的更
改,⽤⼀个新的提交来实现撤销
两者主要区别如下:
git revert是⽤⼀次新的commit来回滚之前的commit,git reset是直接删除指定的commit
git reset 是把HEAD向后移动了⼀下,⽽git revert是HEAD继续前进,只是新的commit的内容和要
revert的内容正好相反,能够抵消要被revert的内容
在回滚这⼀操作上看,效果差不多。但是在⽇后继续 merge 以前的⽼版本时有区别
git revert是⽤⼀次逆向的commit“中和”之前的提交,因此⽇后合并⽼的branch时,之前提交合并的代
码仍然存在,导致不能够重新合并
但是git reset是之间把某些commit在某个branch上删除,因⽽和⽼的branch再次merge时,这些被回
滚的commit应该还会被引⼊
如果回退分⽀的代码以后还需要的情况则使⽤ git revert , 如果分⽀是提错了没⽤的并且不想
让别⼈发现这些错误代码,则使⽤ git reset

10. 说说你对git stash 的理解?应⽤场景?

10.1. 是什么
39 40
stash,译为存放,在 git 中,可以理解为保存当前⼯作进度,会把暂存区和⼯作区的改动进⾏保存,这
些修改会保存在⼀个栈上
后续你可以在任何时候任何分⽀重新将某次的修改推出来,重新应⽤这些更改的代码
默认情况下, git stash 会缓存下列状态的⽂件:
添加到暂存区的修改(staged changes)
Git跟踪的但并未添加到暂存区的修改(unstaged changes)
但以下状态的⽂件不会缓存:
在⼯作⽬录中新的⽂件(untracked files)
被忽略的⽂件(ignored files)
如果想要上述的⽂件都被缓存,可以使⽤ -u 或者 --include-untracked 可以⼯作⽬录新的⽂件,
使⽤ -a 或者 --all 命令可以当前⽬录下的所有修改
关于 git stash 常⻅的命令如下:
git stash
git stash save
git stash list
git stash pop
git stash apply
git stash show
git stash drop
git stash clear
保存当前⼯作进度,会把暂存区和⼯作区的改动保存起来
git stash save 可以⽤于存储修改.并且将 git 的⼯作状态切回到 HEAD 也就是上⼀次合法提交
10.2. 如何使⽤
10.2.1. git stash
10.2.2. git stash save 41
如果给定具体的⽂件路径, git stash 只会处理路径下的⽂件.其他的⽂件不会被存储,其存在⼀些参
数:
--keep-index 或者 -k 只会存储为加⼊ git 管理的⽂件
--include-untracked 为追踪的⽂件也会被缓存,当前的⼯作空间会被恢复为完全清空的状态
-a 或者 --all 命令可以当前⽬录下的所有修改,包括被 git 忽略的⽂件
显示保存进度的列表。也就意味着, git stash 命令可以多次执⾏,当多次使⽤ git stash 命令
后,栈⾥会充满未提交的代码,如下:
其中, stash@{0} stash@{1} 就是当前 stash 的名称
git stash pop 从栈中读取最近⼀次保存的内容,也就是栈顶的 stash 会恢复到⼯作区
也可以通过 git stash pop + stash 名字执⾏恢复哪个 stash 恢复到当前⽬录
如果从 stash 中恢复的内容和当前⽬录中的内容发⽣了冲突,则需要⼿动修复冲突或者创建新的分⽀
来解决冲突
将堆栈中的内容应⽤到当前⽬录,不同于 git stash pop ,该命令不会将内容从堆栈中删除
也就说该命令能够将堆栈的内容多次应⽤到⼯作⽬录中,适应于多个分⽀的情况
同样,可以通过 git stash apply + stash 名字执⾏恢复哪个 stash 恢复到当前⽬录
查看堆栈中最新保存的 stash 和当前⽬录的差异
通过使⽤ git stash show -p 查看详细的不同
通过使⽤ git stash show stash@{1} 查看指定的 stash 和当前⽬录差异
10.2.3. git stash list
10.2.4. git stash pop
10.2.5. git stash apply
10.2.6. git stash show 10.2.7. git stash drop
git stash drop + stash 名称表示从堆栈中移除某个指定的stash
10.2.8. git stash clear
删除所有存储的进度
10.3. 应⽤场景
当你在项⽬的⼀部分上已经⼯作⼀段时间后,所有东⻄都进⼊了混乱的状态, ⽽这时你想要切换到另⼀
个分⽀或者拉下远端的代码去做⼀点别的事情
但是你创建⼀次未完成的代码的 commit 提交,这时候就可以使⽤ git stash
例如以下场景:
当你的开发进⾏到⼀半,但是代码还不想进⾏提交 ,然后需要同步去关联远端代码时.如果你本地的代码和
远端代码没有冲突时,可以直接通过 git pull 解决
但是如果可能发⽣冲突怎么办.直接 git pull 会拒绝覆盖当前的修改,这时候就可以依次使⽤下述的
命令:
git stash
git pull
git stash pop
或者当你开发到⼀半,现在要修改别的分⽀问题的时候,你也可以使⽤ git stash 缓存当前区域的代
42 git stash:保存开发到⼀半的代码
git commit -m '修改问题'
git stash pop:将代码追加到最新的提交之后
43

网站公告

今日签到

点亮在社区的每一天
去签到