git面试题总结
Posted xushiyu1996818
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了git面试题总结相关的知识,希望对你有一定的参考价值。
目录
提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的?
你使用过git stash命令吗?你一般什么情况下会使用它?
git reset、git revert 和 git checkout 有什么区别
能不能说一下git fetch和git pull命令之间的区别?
使用过git merge和git rebase吗?它们之间有什么区别?
我们在本地工程常会修改一些配置文件,这些文件不需要被提交,而我们又不想每次执行git status时都让这些文件显示出来,我们该如何操作?
列举工作中常用的几个git命令?
远程仓库中clone代码到本地:git clone https://github.com/MatchlessHeroVIP/ssmtest.git
新增文件的命令:git add file或者git add .
提交文件的命令:git commit –m或者git commit –a
本地仓库提交到远程仓库:git push
查看工作区状况:git status –s
拉取合并远程分支的操作:git fetch/git merge或者git pull
查看提交记录命令:git reflog
切换到主分支: git checkout master
提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的?
开发过程中,我们都有自己的特性分支,所以冲突发生的并不多,但也碰到过。诸如公共类的公共方法,我和别人同时修改同一个文件,他提交后我再提交就会报冲突的错误。
发生冲突,在IDE里面一般都是对比本地文件和远程分支的文件,然后把远程分支上文件的内容手工修改到本地文件,然后再提交冲突的文件使其保证与远程分支的文件一致,这样才会消除冲突,然后再提交自己修改的部分。特别要注意下,修改本地冲突文件使其与远程仓库的文件保持一致后,需要提交后才能消除冲突,否则无法继续提交。必要时可与同事交流,消除冲突。
发生冲突,也可以使用命令。
通过git stash命令,把工作区的修改提交到栈区,目的是保存工作区的修改;
通过git pull命令,拉取远程分支上的代码并合并到本地分支,目的是消除冲突;
通过git stash pop命令,把保存在栈区的修改部分合并到最新的工作空间中;
如果本次提交误操作,如何撤销?
如果想撤销提交到索引区的文件,可以通过git reset HEAD file;如果想撤销提交到本地仓库的文件,可以通过git reset –soft HEAD^n恢复当前分支的版本库至上一次提交的状态,索引区和工作空间不变更;可以通过git reset –mixed HEAD^n恢复当前分支的版本库和索引区至上一次提交的状态,工作区不变更;可以通过git reset –hard HEAD^n恢复当前分支的版本库、索引区和工作空间至上一次提交的状态。
如果我想修改提交的历史信息,应该用什么命令?
如果修改最近一次提交的历史记录,就可以用git commit –amend命令;vim编辑的方式;
如果修改之前提交的历史记录,就需要按照下面的步骤:
第一步:首先查看前三次的提交历史记录:
$ git log -3
commit a762fcafecbd92bbde088054644e1b0586589c4b (HEAD -> slave)
Author: 18073638 <18073638@cnsuning.com>
Date: Sat Mar 30 10:58:44 2019 +0800
four commit
commit eedbc93d58780f63dd47f8388f8217892096e89a
Author: 18073638 <18073638@cnsuning.com>
Date: Thu Mar 28 17:19:52 2019 +0800
third commit third commit
commit 05396135eba85140602107e01e5c211d74f6c739
Author: 18073638 <18073638@cnsuning.com>
Date: Thu Mar 28 16:56:19 2019 +0800
second commit
注意:这里我们想把053961的committer对象信息修改为“second commit second commit”.
第二步:执行命令git rebase –i HEAD~3,会把前3次的提交记录按照倒叙列出来;
pick 0539613 second commit
pick eedbc93 third commit third commit
pick a762fca four commit
# Rebase c8d7ad7..a762fca onto c8d7ad7 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
这里把第一行的‘pick’修改为‘edit’,然后esc + :wq退出vim编辑器;
$ git rebase -i HEAD~3
Stopped at 0539613... second commit
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
第三步:根据提示,执行git commit –amend命令,进入vim编辑器并修改提交信息。
$ git commit --amend
[detached HEAD 20fe643] second commit second commit
Date: Thu Mar 28 16:56:19 2019 +0800
1 file changed, 1 insertion(+)
第四步:然后执行git rebase –continue命令
$ git rebase --continue
Successfully rebased and updated refs/heads/slave.
查看修改结果
$ git log -3
commit 9024049ef990e79fa61295d5c2b64d70017cf412 (HEAD -> slave)
Author: 18073638 <18073638@cnsuning.com>
Date: Sat Mar 30 10:58:44 2019 +0800
four commit
commit 79cb4e26dd300591e6352d0488802f43b65c8ba2
Author: 18073638 <18073638@cnsuning.com>
Date: Thu Mar 28 17:19:52 2019 +0800
third commit third commit
commit 20fe643cbf80cdcc649d732065e8ebf4caf773c7
Author: 18073638 <18073638@cnsuning.com>
Date: Thu Mar 28 16:56:19 2019 +0800
second commit second commit
修改成功。
git的4个区域及转换
Git本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。如果在加上远程的git仓库(Remote Directory)就可以分为四个工作区域。文件在这四个区域之间的转换关系如下:
Workspace:工作区,就是你平时存放项目代码的地方;
Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息,一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index);
Repository:仓库区(或本地仓库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本;
Remote:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换;
本地的三个区域确切的说应该是git仓库中HEAD指向的版本:
Directory:使用Git管理的一个目录,也就是一个仓库,包含我们的工作空间和Git的管理空间。
WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间。
.git:存放Git管理信息的目录,初始化仓库的时候自动创建。
Index/Stage:暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区。
Local Repo:本地仓库,一个存放在本地的版本库;HEAD会只是当前的开发分支(branch)。
你使用过git stash命令吗?你一般什么情况下会使用它?
命令git stash是把工作区修改的内容存储在栈区。
以下几种情况会使用到它:
解决冲突文件时,会先执行git stash,然后解决冲突;
遇到紧急开发任务但目前任务不能提交时,会先执行git stash,然后进行紧急任务的开发,然后通过git stash pop取出栈区的内容继续开发;
切换分支时,当前工作空间内容不能提交时,会先执行git stash再进行分支切换;
git add和git statsh的区别
在回答这个问题之前需要先了解 git 仓库的三个组成部分:工作区(Working Directory)、暂存区(Stage)和历史记录区(History):
工作区:在 git 管理下的正常目录都算是工作区,我们平时的编辑工作都是在工作区完成。
暂存区:临时区域。里面存放将要提交文件的快照。
历史记录区:git commit 后的记录区。
然后是这三个区的转换关系以及转换所使用的命令:
然后我们就可以来说一下 git add 和 git stage 了。其实,他们两是同义的,所以,惊不惊喜,意不意外?这个问题竟然是个陷阱…
引入 git stage 的原因其实比较有趣:
是因为要跟 svn add 区分,两者的功能是完全不一样的,svn add 是将某个文件加入版本控制,而 git add 则是把某个文件加入暂存区,因为在 git 出来之前大家用 svn 比较多,所以为了避免误导,git 引入了git stage,然后把 git diff –staged 做为 git diff –cached 的相同命令。基于这个原因,我们建议使用 git stage 以及 git diff –staged。
git add . 和 git add * 区别
git add . 会把本地所有untrack的文件都加入暂存区,并且会根据.gitignore做过滤,但是git add * 会提示已被忽略的内容,但不会直接加入
git add和git commit的区别
要想弄明白git add和git commit的区别,首先我们需要知道三个概念:工作区(Working Directory)、版本库(Repository)、暂存区(Stage or index)。
工作区
当你在开发一个项目时,主目录就是你的工作区。
版本库
工作区中有一个隐藏目录.git,这个就是git的版本库了。
暂存区
Git的版本库里存了很多文件,其中包括称为Stage或index的暂存区,还有一个git为我们自动创建的第一个分支master,以及指向master的一个指针HEAD。
下面就是三个区的示意图:图片来着廖雪峰老师的 博客。
三个区的示意图三个区的示意图
git add和git commit的区别就在于:
git add把文件添加进去,实际上就是把文件修改添加到暂存区;
git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支。所以,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
所以要想将修改提交到master中一定要先git add到暂存区中,再git commit到master分支。
如何查看分支提交的历史记录?查看某个文件的历史记录呢?
查看分支的提交历史记录:
命令git log –number:表示查看当前分支前number个详细的提交历史记录;
命令git log –number –pretty=oneline:在上个命令的基础上进行简化,只显示sha-1码和提交信息;
命令git reflog –number: 表示查看所有分支前number个简化的提交历史记录;
命令git reflog –number –pretty=oneline:显示简化的信息历史信息;
如果要查看某文件的提交历史记录,直接在上面命令后面加上文件名即可。
注意:如果没有number则显示全部提交次数。
git reset、git revert 和 git checkout 有什么区别
这个问题同样也需要先了解 git 仓库的三个组成部分:工作区(Working Directory)、暂存区(Stage)和历史记录区(History)。
首先是它们的共同点:用来撤销代码仓库中的某些更改。
然后是不同点:
首先,从 commit 层面来说:
git reset 可以将一个分支的末端指向之前的一个 commit。然后再下次 git 执行垃圾回收的时候,会把这个 commit 之后的 commit 都扔掉。git reset 还支持三种标记,用来标记 reset 指令影响的范围:
–mixed:会影响到暂存区和历史记录区。也是默认选项;
–soft:只影响历史记录区;
–hard:影响工作区、暂存区和历史记录区。
注意:因为 git reset 是直接删除 commit 记录,从而会影响到其他开发人员的分支,所以不要在公共分支(比如 develop)做这个操作。
git checkout 可以将 HEAD 移到一个新的分支,并更新工作目录。因为可能会覆盖本地的修改,所以执行这个指令之前,你需要 stash 或者 commit 暂存区和工作区的更改。
git revert 和 git reset 的目的是一样的,但是做法不同,它会以创建新的 commit 的方式来撤销 commit,这样能保留之前的 commit 历史,比较安全。另外,同样因为可能会覆盖本地的修改,所以执行这个指令之前,你需要 stash 或者 commit 暂存区和工作区的更改。
然后,从文件层面来说:
git reset 只是把文件从历史记录区拿到暂存区,不影响工作区的内容,而且不支持 –mixed、–soft 和 –hard。
git checkout 则是把文件从历史记录拿到工作区,不影响暂存区的内容。
git revert 不支持文件层面的操作。
回答关键点:
对于 commit 层面和文件层面,这三个指令本身功能差别很大。
git revert 不支持文件层面的操作。
不要在公共分支做 git reset 操作。
能不能说一下git fetch和git pull命令之间的区别?
git pull 命令从中央存储库中提取特定分支的新更改或提交,并更新本地存储库中的目标分支。
git fetch 也用于相同的目的,但它的工作方式略有不同。当你执行 git fetch 时,它会从所需的分支中提取所有新提交,并将其存储在本地存储库中的新分支中。如果要在目标分支中反映这些更改,必须在 git fetch 之后执行git merge。只有在对目标分支和获取的分支进行合并后才会更新目标分支。
为了方便起见,请记住以下等式:
git pull = git fetch + git merge
使用过git merge和git rebase吗?它们之间有什么区别?
简单的说,git merge和git rebase都是合并分支的命令。
git merge branch会把branch分支的差异内容pull到本地,然后与本地分支的内容一并形成一个committer对象提交到主分支上,合并后的分支与主分支一致;
git rebase branch会把branch分支优先合并到主分支,然后把本地分支的commit放到主分支后面,合并后的分支就好像从合并后主分支又拉了一个分支一样,本地分支本身不会保留提交历史。
能说一下git系统中HEAD、工作树和索引之间的区别吗?
HEAD文件包含当前分支的引用(指针);
工作树是把当前分支检出到工作空间后形成的目录树,一般的开发工作都会基于工作树进行;
索引index文件是对工作树进行代码修改后,通过add命令更新索引文件;GIT系统通过索引index文件生成tree对象;
GitFlow工作流程分支有哪些
GitFlow可以用来管理分支。GitFlow工作流中常用的分支有下面几类:
master分支:最为稳定功能比较完整的随时可发布的代码,即代码开发完成,经过测试,没有明显的bug,才能合并到 master 中。请注意永远不要在 master 分支上直接开发和提交代码,以确保 master 上的代码一直可用;
develop分支;用作平时开发的主分支,并一直存在,永远是功能最新最全的分支,包含所有要发布 到下一个 release 的代码,主要用于合并其他分支,比如 feature 分支; 如果修改代码,新建 feature 分支修改完再合并到 develop 分支。所有的 feature、release 分支都是从 develop 分支上拉的。
feature分支;这个分支主要是用来开发新的功能,一旦开发完成,通过测试没问题(这个测试,测试新功能没问题),我们合并回develop 分支进入下一个 release
release分支;用于发布准备的专门分支。当开发进行到一定程度,或者说快到了既定的发布日,可以发布时,建立一个 release 分支并指定版本号(可以在 finish 的时候添加)。开发人员可以对 release 分支上的代码进行集中测试和修改bug。(这个测试,测试新功能与已有的功能是否有冲突,兼容性)全部完成经过测试没有问题后,将 release 分支上的代码合并到 master 分支和 develop 分支
hotfix分支;用于修复线上代码的bug。**从 master 分支上拉。**完成 hotfix 后,打上 tag 我们合并回 master 和 develop 分支。
GitFlow主要工作流程
1.初始化项目为gitflow , 默认创建master分支 , 然后从master拉取第一个develop分支
2.从develop拉取feature分支进行编码开发(多个开发人员拉取多个feature同时进行并行开发 , 互不影响)
3.feature分支完成后 , 合并到develop(不推送 , feature功能完成还未提测 , 推送后会影响其他功能分支的开发);合并feature到develop , 可以选择删除当前feature , 也可以不删除。但当前feature就不可更改了,必须从release分支继续编码修改
4.从develop拉取release分支进行提测 , 提测过程中在release分支上修改BUG
5.release分支上线后 , 合并release分支到develop/master并推送;合并之后,可选删除当前release分支,若不删除,则当前release不可修改。线上有问题也必须从master拉取hotfix分支进行修改;
6.上线之后若发现线上BUG , 从master拉取hotfix进行BUG修改;
7.hotfix通过测试上线后,合并hotfix分支到develop/master并推送;合并之后,可选删除当前hotfix ,若不删除,则当前hotfix不可修改,若补丁未修复,需要从master拉取新的hotfix继续修改;
8.当进行一个feature时 , 若develop分支有变动 , 如其他开发人员完成功能并上线 , 则需要将完成的功能合并到自己分支上,即合并develop到当前feature分支;
9.当进行一个release分支时 , 若develop分支有变动 , 如其他开发人员完成功能并上线 , 则需要将完成的功能合并到自己分支上,即合并develop到当前release分支 (!!! 因为当前release分支通过测试后会发布到线上 , 如果不合并最新的develop分支 , 就会发生丢代码的情况);
GitFlow的好处
GitFlow为不同的分支分配一个明确的角色,并定义分支之间如何交互以及什么时间交互;可以帮助大型项目理清分支之间的关系,简化分支的复杂度。
使用过git cherry-pick,有什么作用?
命令git cherry-pick可以把branch A的commit复制到branch B上。
在branch B上进行命令操作:
复制单个提交:git cherry-pick commitId
复制多个提交:git cherry-pick commitId1…commitId3
注意:复制多个提交的命令不包含commitId1.
git跟其他版本控制器有啥区别?
GIT是分布式版本控制系统,其他类似于SVN是集中式版本控制系统。
分布式区别于集中式在于:每个节点的地位都是平等,拥有自己的版本库,在没有网络的情况下,对工作空间内代码的修改可以提交到本地仓库,此时的本地仓库相当于集中式的远程仓库,可以基于本地仓库进行提交、撤销等常规操作,从而方便日常开发。
我们在本地工程常会修改一些配置文件,这些文件不需要被提交,而我们又不想每次执行git status时都让这些文件显示出来,我们该如何操作?
首先利用命令touch .gitignore新建文件
$ touch .gitignore
然后往文件中添加需要忽略哪些文件夹下的什么类型的文件
$ vim .gitignore
$ cat .gitignore
/target/class
.settings
.imp
*.ini
注意:忽略/target/class文件夹下所有后缀名为.settings,.imp的文件,忽略所有后缀名为.ini的文件。
如何把本地仓库的内容推向一个空的远程仓库?
首先确保本地仓库与远程之间是连同的。如果提交失败,则需要进行下面的命令进行连通:
git remote add origin XXXX
注意:XXXX是你的远程仓库地址。
如果是第一次推送,则进行下面命令:
git push -u origin master
注意:-u 是指定origin为默认主分支
之后的提交,只需要下面的命令:
git push origin master
如果代码出现bug,你们是如何解决的?
创建一个bug分支,然后进行bug处理,处理完毕后,合并到review分支,组长review成功后才能够合并到master
合并完成之后删除bug分支
回到dev分支继续开发。
git rebase的作用?
场景:在公司开发忘记提交到github托管,在家里又继续开发新的功能,
然后到公司昨天的代码跟你的新功能合并的时候可以用git fecth ---> git rebase
那么他的提交记录就不会出现分叉,保持了提交记录的整洁.
如何做代码的review?
创建review分支,然后再创建自己的个人分支,当你完成自己的业务逻辑的时候,
再合并到review分支.给组长做代码的review
以上是关于git面试题总结的主要内容,如果未能解决你的问题,请参考以下文章