面试题--Git与设计模式

面试题--Git与设计模式

Git

1、Git和SVN有什么区别?

在这里插入图片描述

2、什么是Git?

我建议你先通过了解 git 的架构再来回答这个问题,如下图所示,试着解释一下这个图:
Git 是分布式版本控制系统(DVCS)。它可以跟踪文件的更改,并允许你恢复到任何特定版本的更改。

与 SVN 等其他版本控制系统(VCS)相比,其分布式架构具有许多优势,一个主要优点是它不依赖于中央服务器来存储项目文件的所有版本。

每个开发人员都可以“克隆”我在图中用“Local repository”标注的存储库的副本,并且在他的硬盘驱动器上具有项目的完整历史记录,因此当服务器中断时,你需要的所有恢复数据都在你队友的本地 Git 存储库中。

还有一个中央云存储库,开发人员可以向其提交更改,并与其他团队成员进行共享,如图所示,所有协作者都在提交更改“远程存储库”。
在这里插入图片描述

3、在 Git 中提交的命令是什么?

答案非常简单。 用于写入提交的命令是 git commit -a。

现在解释一下 -a 标志, 通过在命令行上加 -a 指示 git 提交已修改的所有被跟踪文件的新内容。还要提一下,如果你是第一次需要提交新文件,可以在在 git commit -a 之前先 git add 。

4、什么是 Git 中的“裸存储库”?

你应该说明 “工作目录” 和 “裸存储库” 之间的区别。

Git 中的 “裸” 存储库只包含版本控制信息而没有工作文件(没有工作树),并且它不包含特殊的.git 子目录。相反,它直接在主目录本身包含 .git 子目录中的所有内容,其中工作目录包括:

  1. 一个 .git 子目录,其中包含你的仓库所有相关的 Git 修订历史记录。
  2. 工作树,或签出的项目文件的副本。

5、Git 是用什么语言编写的?

Git使用 C 语言编写。 GIT 很快,C 语言通过减少运行时的开销来做到这一点。

6、在Git中,你如何还原已经 push 并公开的提交?

删除或修复新提交中的错误文件,并将其推送到远程存储库。这是修复错误的最自然方式。对文件进行必要的修改后,将其提交到我将使用的远程存储库。

git commit -m “commit message”

创建一个新的提交,撤消在错误提交中所做的所有更改。可以使用命令:

git revert <name of bad commit>

7、git pull 和 git fetch 有什么区别?

git pull 命令从中央存储库中提取特定分支的新更改或提交,并更新本地存储库中的目标分支。

git fetch 也用于相同的目的,但它的工作方式略有不同。当你执行 git fetch 时,它会从所需的分支中提取所有新提交,并将其存储在本地存储库中的新分支中。如果要在目标分支中反映这些更改,必须在 git fetch 之后执行 git merge 。只有在对目标分支和获取的分支进行合并后才会更新目标分支。为了方便起见,请记住以下等式:

git pull = git fetch + git merge

8、git中的“staging area”或“index”是什么?

For this answer try to explain the below diagram as you can see: 可以通过下图进行解释:在完成提交之前,可以在称为“staging area”或“index”的中间区域中对其进行格式化和审查。从图中可以看出,每个更改首先在暂存区域中进行验证,我将其称为“stage file”,然后将更改提交到存储库。
在这里插入图片描述

9、什么是 git stash?

首先应该解释 git stash 的必要性。

通常情况下,当你一直在处理项目的某一部分时,如果你想要在某个时候切换分支去处理其他事情,事情会处于混乱的状态。问题是,你不想把完成了一半的工作的提交,以便你以后就可以回到当前的工作。解决这个问题的答案是 git stash。
再解释什么是git stash。stash 会将你的工作目录,即修改后的跟踪文件和暂存的更改保存在一堆未完成的更改中,你可以随时重新应用这些更改。

10、什么是git stash drop?

通过说明我们使用 git stash drop 的目的来回答这个问题。
git stash drop 命令用于删除隐藏的项目。默认情况下,它将删除最后添加的存储项,如果提供参数的话,它还可以删除特定项。

下面举个例子。
如果要从隐藏项目列表中删除特定的存储项目,可以使用以下命令:

git stash list:它将显示隐藏项目列表,如:stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051Revert “added file_size” stash@{2}: WIP on master: 21d80a5 added number to log如果要删除名为 stash@{0} 的项目,请使用命令 git stash drop stash@{0}。

11.、如何找到特定提交中已更改的文件列表?

对于这个问题,不能仅仅是提供命令,还要解释这个命令究竟做了些什么。
要获取特定提交中已更改的列表文件,请使用以下命令:
git diff-tree -r {hash}
给定提交哈希,这将列出在该提交中更改或添加的所有文件。 -r 标志使命令列出单个文件,而不是仅将它们折叠到根目录名称中。
你还可以包括下面提到的内容,虽然它是可选的,但有助于给面试官留下深刻印象。
输出还将包含一些额外信息,可以通过包含两个标志把它们轻松的屏蔽掉:
git diff-tree –no-commit-id –name-only -r {hash}
这里 -no-commit-id 将禁止提交哈希值出现在输出中,而 -name-only 只会打印文件名而不是它们的路径。

12、git config 的功能是什么?

首先说明为什么我们需要 git config 。
git 使用你的用户名将提交与身份相关联。 git config 命令可用来更改你的 git 配置,包括你的用户名。
下面用一个例子来解释。
假设你要提供用户名和电子邮件 ID 用来将提交与身份相关联,以便你可以知道是谁进行了特定提交。为此,我将使用:
git config –global user.name “Your Name”: 此命令将添加用户名。
git config –global user.email “Your E-mail Address”: 此命令将添加电子邮件ID。

13、提交对象包含什么?

Commit 对象包含以下组件,你应该提到以下这三点:

一组文件,表示给定时间点的项目状态
引用父提交对象
SHAI 名称,一个40个字符的字符串,提交对象的唯一标识.

14、 如何在Git中创建存储库?

这可能是最常见的问题,答案很简单。
要创建存储库,先为项目创建一个目录(如果该目录不存在),然后运行命令 git init。通过运行此命令,将在项目的目录中创建 .git 目录。

15、怎样将 N 次提交压缩成一次提交?

将N个提交压缩到单个提交中有两种方式:
如果要从头开始编写新的提交消息,请使用以下命令:

git reset –soft HEAD~N &&
git commit

如果你想在新的提交消息中串联现有的提交消息,那么需要提取这些消息并将它们传给 git
commit,可以这样:

git reset –soft HEAD~N &&
git commit –edit -m"$(git log –format=%B –reverse .HEAD@{N})"

16、 什么是 Git bisect?如何使用它来确定(回归)错误的来源?

我建议你先给出一个Git bisect 的小定义。
Git bisect 用于查找使用二进制搜索引入错误的提交。 Git bisect的命令是

git bisect <subcommand> <options>

既然你已经提到过上面的命令,那就解释一下这个命令会做什么。

此命令用了二进制搜索算法来查找项目历史记录中的哪个提交引入了错误。你可以通过告诉它已知包含该错误的“错误”提交以及在引入错误之前已知的“良好”提交来使用它。然后 git bisect 在这两个端点之间选择一个提交,并询问你所选的提交是“好”还是“坏”。它继续缩小范围,直到找到引入更改的确切提交。

17、如果想要在提交之前运行代码性检查工具,并在测试失败时阻止提交,该怎样配置 Git 存储库?

我建议你先介绍一下完整性检查。
完整性或冒烟测试用来确定继续测试是否可行和合理。
下面解释如何实现这一目标。

这可以通过与存储库的 pre-commit hook 相关的简单脚本来完成。git 会在提交之前触发 precommit hook。你可以在这个脚本中运行其他工具,例如 linters,并对提交到存储库中的更改执行完整性检查。
最后举个例子,你可以参考下面的脚本:

#!/bin/sh
files=$(git diff –cached –name-only –diff-filter=ACM | grep ‘.go$’)
if [ -z files ]; then
 exit 0
fi
unfmtd=$(gofmt -l $files)
if [ -z unfmtd ]; then
 exit 0
fi
echo “Some .go files are not fmt’d”
exit 1

这段脚本检查是否需要通过标准 Go 源代码格式化工具 gofmt 传递所有即将提交的 .go 文件。如果脚步以非 0 状态退出,脚本会有效地阻止提交操作。

18.、描述一下你所使用的分支策略?

这个问题被要求用Git来测试你的分支经验,告诉他们你在以前的工作中如何使用分支以及它的用途是什么,你可以参考以下提到的要点:
功能分支(Feature branching)
要素分支模型将特定要素的所有更改保留在分支内。当通过自动化测试对功能进行全面测试和验证时,该分支将合并到主服务器中。
任务分支(Task branching)
在此模型中,每个任务都在其自己的分支上实现,任务键包含在分支名称中。很容易看出哪个代码实现了哪个任务,只需在分支名称中查找任务键。
发布分支(Release branching)
一旦开发分支获得了足够的发布功能,你就可以克隆该分支来形成发布分支。创建该分支将会启动下一个发布周期,所以在此之后不能再添加任何新功能,只有错误修复,文档生成和其他面向发布的任务应该包含在此分支中。一旦准备好发布,该版本将合并到主服务器并标记版本号。此外,它还应该再将自发布以来已经取得的进展合并回开发分支。

最后告诉他们分支策略因团队而异,所以我知道基本的分支操作,如删除、合并、检查分支等。

19、如果分支是否已合并为master,你可以通过什么手段知道?

答案很直接。
要知道某个分支是否已合并为master,你可以使用以下命令:
git branch –merged 它列出了已合并到当前分支的分支。
git branch –no-merged 它列出了尚未合并的分支。

20、 什么是SubGit?

SubGit 是将 SVN 到 Git迁移的工具。它创建了一个可写的本地或远程 Subversion 存储库的 Git 镜像,并且只要你愿意,可以随意使用 Subversion 和 Git。

这样做有很多优点,比如你可以从 Subversion 快速一次性导入到 Git 或者在 Atlassian BitbucketServer 中使用SubGit。我们可以用 SubGit 创建现有 Subversion 存储库的双向 Git-SVN 镜像。你可以在方便时 push 到 Git 或提交 Subversion。同步由 SubGit 完成。

21、列举工作中常用的几个git命令?

新增文件的命令:git add file或者git add . 提交文件的命令:git commit –m或者git commit –a 查看工作区状况:git status –s 拉取合并远程分支的操作:git fetch/git merge或者git pull 查看提交记录命令:git reflog

22、如果本次提交误操作,如何撤销?

如果想撤销提交到索引区的文件,可以通过git reset HEAD file;如果想撤销提交到本地仓库的文件,可以通过git reset –soft HEAD^n恢复当前分支的版本库至上一次提交的状态,索引区和工作空间不变更;可以通过git reset –mixed HEAD^n恢复当前分支的版本库和索引区至上一次提交的

23、你使用过git stash命令吗?你一般什么情况下会使用它?

命令git stash是把工作区修改的内容存储在栈区。 以下几种情况会使用到它:
解决冲突文件时,会先执行git stash,然后解决冲突;

遇到紧急开发任务但目前任务不能提交时,会先执行git stash,然后进行紧急任务的开发,然后通过git stash pop取出栈区的内容继续开发;

切换分支时,当前工作空间内容不能提交时,会先执行git stash再进行分支切换;

24、如何查看分支提交的历史记录?查看某个文件的历史记录呢?

查看分支的提交历史记录:
命令git log –number:表示查看当前分支前number个详细的提交历史记录;
命令git log –number –pretty=oneline:在上个命令的基础上进行简化,只显示sha-1码和提交信息;
命令git reflog –number: 表示查看所有分支前number个简化的提交历史记录;
命令git reflog –number –pretty=oneline:显示简化的信息历史信息;

如果要查看某文件的提交历史记录,直接在上面命令后面加上文件名即可。
注意:如果没有number则显示全部提交次数。

25、使用过git merge和git rebase吗?它们之间有什么区别?

简单的说,git merge和git rebase都是合并分支的命令。 git merge branch会把branch分支的差异内容pull到本地,然后与本地分支的内容一并形成一个committer对象提交到主分支上,合并后的分支与主分支一致; git rebase branch会把branch分支优先合并到主分支,然后把本地分支的commit放到主分支后面,合并后的分支就好像从合并后主分支又拉了一个分支一样,本地分支本身不会保留提交历史。

26、使用过git cherry-pick,有什么作用?

命令git cherry-pick可以把branch A的commit复制到branch B上。 在branch B上进行命令操作:
复制单个提交:git cherry-pick commitId
复制多个提交:git cherry-pick commitId1…commitId3
注意:复制多个提交的命令不包含commitId1

设计模式

在这里插入图片描述
设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。

1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。
通常面试中会问:
说一下你知道哪些设计模式?
这时候,就得需要平时积累下来的经验了,肯定回答自己会的,你只是知道名词是没用用的。从难易程度和常用情况来看可以这么回答:

单例模式、代理模式、模板方法模式、装饰器模式、工厂模式、责任链模式、观察者模式、原型模式。

通常你能回答这么多就已经ok了。但是其他模式,可以适当的了解了解,不然面试官问你还有其他设计模式吗?
这时候,你就可以回答名词了,他再问,你就说这些设计模式只是了解过,在工作中用的不是很多。

1、说说什么是单例模式

答:单例模式是一种常用的软件设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例。
优点:不会频繁地创建和销毁对象,浪费系统资源。
可能这会需要你手写一个单例模式,这就得自己去学了,因为单例模式有很多种写法,懒汉模式,饿汉模式,双重检查模式等。懒汉模式就是用的时候再去创建对象,饿汉模式就是提前就已经加载好的静态static对象,双重检查模式就是两次检查避免多线程造成创建了多个对象。
单例模式有很多种的写法,我总结一下:
(1)饿汉式单例模式的写法:线程安全
(2)懒汉式单例模式的写法:非线程安全
(3)双检锁单例模式的写法:线程安全

2、说说你对代理模式的理解

代理模式是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
优点:
代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;
可以灵活地隐藏被代理对象的部分功能和服务,也增加额外的功能和服务。
缺点:
由于使用了代理模式,因此程序的性能没有直接调用性能高;
使用代理模式提高了代码的复杂度。

黄牛卖火车票:没有流行网络购票的年代是很喜欢找黄牛买火车票的,因为工作忙的原因,没时间去买票,然后就托黄牛给你买张回家过年的火车票。这个过程中黄牛就是代理人,火车票就是被代理的对象。

婚姻介绍所:婚姻介绍所的工作人员,搜集单身人士信息,婚介所的工作人员为这个单身人士找对象,这个过程也是代理模式的生活案例。对象就是被代理的对象。

注意了,问代理模式的时候,很有可能会问:动态代理。在Spring篇中已经讲述过,如果你把动态代理讲了后,很有可能还会问什么是静态代理?一个洞一个是静,大致也能才出来,就是中间代理层使我们手动写的,通常说的代理模式就是静态代理。

3、说说工厂模式

答:简单工厂模式又叫静态工厂方法模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。比如,一台咖啡机就可以理解为一个工厂模式,你只需要按下想喝的咖啡品类的按钮(摩卡或拿铁),它就会给你生产一杯相应的咖啡,你不需要管它内部的具体实现,只要告诉它你的需求即可。
优点:
工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象;

客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量;

通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑;

产品类型较多时,工厂的创建逻辑可能过于复杂,一旦出错可能造成所有产品的创建失败,不利于系统的维护。

4、抽象工厂模式

答:抽象工厂模式是在简单工厂的基础上将未来可能需要修改的代码抽象出来,通过继承的方式让子类去做决定。

比如,以上面的咖啡工厂为例,某天我的口味突然变了,不想喝咖啡了想喝啤酒,这个时候如果直接修改简单工厂里面的代码,这种做法不但不够优雅,也不符合软件设计的“开闭原则”,因为每次新增品类都要修改原来的代码。这个时候就可以使用抽象工厂类了,抽象工厂里只声明方法,具体的实现交给子类(子工厂)去实现,这个时候再有新增品类的需求,只需要新创建代码即可。

5、装饰器模式是什么

答:装饰器模式是指动态地给一个对象增加一些额外的功能,同时又不改变其结构。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

装饰器模式的关键:装饰器中使用了被装饰的对象。

比如,创建一个对象“laowang”,给对象添加不同的装饰,穿上夹克、戴上帽子…,这个执行过程就是装饰者模式。

一句名言:人靠衣裳马靠鞍。都是装饰器模式的生活案列。

6、代理模式和装饰器模式有什么区别?

答:都是结构型模式,代理模式重在访问权限的控制,而装饰器模式重在功能的加强。

7、模板方法模式

答:模板方法模式是指定义一个算法骨架,将具体内容延迟到子类去实现。
优点:
提高代码复用性:将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中;
实现了反向控制:通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制并且符合开闭原则。

喝茶茶:烧水----放入茶叶—喝茶。放入的茶叶每个人自己的喜好不一样,有的是普洱、有的是铁观音等。

每日工作:上班打卡----工作—下班打卡。每个人工作的内容不一样,后端开发的、前端开发、测试、产品每个人的工作内容不一样。

8、知道享元模式吗?

答:顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。
具体来讲,当一个系统中存在大量重复对象的时候,如果这些重复的对象是不可变对象,我们就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用。这样可以减少内存中对象的数量,起到节省内存的目的。
典型的使用场景:Integer中cache,就是享元模式很经典的实现。
怎么看起来享元模式和单例模式是一毛一样的?面试官很有可能会继续问:

9、享元模式和单例模式的区别?

答:单例模式是创建型模式,重在只能有一个对象。而享元模式是结构型模式,重在节约内存使用,提升程序性能。
享元模式:把一个或者多可对象霍村起来,用的时候,直接从缓存里获取。也就是说享元模式不一定只有一个对象。

10、说说策略模式在我们生活的场景

答:策略模式是指定义一系列算法,将每个算法都封装起来,并且使他们之间可以相互替换。
优点:遵循了开闭原则,扩展性良好。
缺点:随着策略的增加,对外暴露越来越多。
条条大路通罗马,条条大路通北京。
我们去北京的交通方式(策略)很多,比如说坐飞机、坐高铁、自己开车等方式。每一种方式就可以理解为每一种策略。
这就是生活中的策略模式。

11、知道责任链模式吗?

答:是行为型设计模式之一,其将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。
优点
解耦了请求与处理;
请求处理者(节点对象)只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一级节点对象;
具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果;
链路结构灵活,可以通过改变链路结构动态地新增或删减责任;
易于扩展新的请求处理类(节点),符合 开闭原则;
缺点
责任链路过长时,可能对请求传递处理效率有影响;
如果节点对象存在循环引用时,会造成死循环,导致系统崩溃;

生活案列:我们在公司内部发起一个OA审批流程,项目经理审批、部门经理审批。老板审批、人力审批。这就是生活中的责任链模式,每个角色的责任是不同。

SpringMVC中的拦截器和Mybatis中的插件机制,都是拦截器经典实现。

12、了解过适配器模式么?

答:适配器模式是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作。
优点:
可以让两个没有关联的类一起运行,起着中间转换的作用;
灵活性好,不会破坏原有的系统。
缺点:
过多地使用适配器,容易使代码结构混乱,如明明看到调用的是 A 接口,内部调用的却是 B接口的实现。

生活中的插座,为了适应各种插头,然后上面有两个孔的,三个空的,基本都能适应。还有万能充电器、USB接口等。这些都是生活中的适配器模式。

13、知道观察者模式吗?

答:观察者模式是定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
优点:
观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;
观察者模式在观察目标和观察者之间建立一个抽象的耦合;
观察者模式支持广播通信;
观察者模式符合开闭原则(对拓展开放,对修改关闭)的要求。
缺点:
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
在观察者模式中有如下角色:
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象;
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知;
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己;
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

在Spring中大量的使用的观察者模式,只要看到是以Event结尾或者Publish开头的基本上都是观察者模式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单眼皮女孩i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值