Git 代码管理面试59题(一)

1. 简述Github和Gitlab的区别?

参考回答:

Github是一个基于git实现在线代码托管的仓库,向互联网开放,企业版要收钱。gitlab类似 github,一般用于在企业内搭建git私服,要自己搭环境。GitHub如果使用私有仓库,是需要付费的,GitLab可以在上面搭建私人的免费仓库。GitLab让开发团队对他们的代码仓库拥有更多的控制,相对于GitHub,它有不少的特色。

GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。
GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。

GitLab由乌克兰程序员DmitriyZaporozhets和ValerySizov开发,它使用Ruby语言写成。后来,一些部分用Go语言重写。截止2018年5月,该公司约有290名团队成员,以及2000多名开源贡献者。GitLab被IBM,Sony,JülichResearchCenter,NASA,Alibaba,Invincea,O'ReillyMedia,Leibniz-Rechenzentrum(LRZ),CERN,SpaceX等组织使用。
2 . 重点简述Git 中 merge 和 rebase命令 的区别?

参考回答:

1.采用merge和rebase后,git log的区别,merge命令不会保留merge的分支的commit:

2.处理冲突的方式:
(一股脑)使用merge命令合并分支,解决完冲突,执行git add .和git commit -m'fix conflict'。这个时候会产生一个commit。
(交互式)使用rebase命令合并分支,解决完冲突,执行git add .和git rebase --continue,不会产生额外的commit。这样的好处是,'干净',分支上不会有无意义的解决分支的commit;坏处,如果合并的分支中存在多个commit,需要重复处理多次冲突。

3.git pull和git pull --rebase区别:git pull做了两个操作分别是'获取'和合并。所以加了rebase就是以rebase的方式进行合并分支,默认为merge。

注意:只有在冲突的时候,解决完冲突才会自动产生一个commit。
如果想在没有冲突的情况下也自动生成一个commit,记录此次合并就可以用:git merge --no-ff命令,
如果不加 --no-ff 则被合并的分支之前的commit都会被抹去,只会保留一个解决冲突后的 merge commit。
4 . 简述Git的版本控制模型是什么(简单)?

参考回答:

Git的版本控制模型是基于快照(snapshot)的,即将文件的每个版本保存为一个完整的快照,而不是仅保存修改的差异。每个快照都有一个唯一的哈希值来标识,这使得Git可以快速查找、比较和恢复文件的任意版本。同时,Git通过分支的方式支持多人协作,每个分支都可以独立地修改、提交、合并和删除。
5 . 简述Git的三种状态是什么?

参考回答:

Git有三种状态:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示数据已经安全地保存在本地数据库中,已修改表示修改了文件但还没有保存到数据库中,已暂存表示对一个已修改文件的当前版本做了标记,使它包含在下次提交的快照中。
6 . 简述什么是SubGit?

参考回答:

SubGit 是将 SVN 到 Git迁移的工具。它创建了一个可写的本地或远程 Subversion 存储库的 Git 镜像,并且只要你愿意,可以随意使用 Subversion 和 Git。
这样做有很多优点,比如你可以从 Subversion 快速一次性导入到 Git 或者在 Atlassian Bitbucket Server 中使用SubGit。我们可以用 SubGit 创建现有 Subversion 存储库的双向 Git-SVN 镜像。你可以在方便时 push 到 Git 或提交 Subversion。同步由 SubGit 完成。
7 . 描述一下你所使用的分支策略?

参考回答:

你可以参考以下提到的要点:

1功能分支(Feature branching)
要素分支模型将特定要素的所有更改保留在分支内。当通过自动化测试对功能进行全面测试和验证时,该分支将合并到主服务器中。

2任务分支(Task branching)
在此模型中,每个任务都在其自己的分支上实现,任务键包含在分支名称中。很容易看出哪个代码实现了哪个任务,只需在分支名称中查找任务键。

3 发布分支(Release branching)
一旦开发分支获得了足够的发布功能,你就可以克隆该分支来形成发布分支。创建该分支将会启动下一个发布周期,所以在此之后不能再添加任何新功能,只有错误修复,文档生成和其他面向发布的任务应该包含在此分支中。一旦准备好发布,该版本将合并到主服务器并标记版本号。此外,它还应该再将自发布以来已经取得的进展合并回开发分支。
8 . 简述GitLabFlow的分支类型和作用 ?

参考回答:

GitLabFlow出现的最晚,GitLabFlow是开源工具GitLab推荐的做法。

GitLabFlow支持GitFlow的分支策略,也支持GitHubFlow的"Pull Request"(在GitLabFlow中被称为"Merge Request")。

相比于GitHubFlow,GitLabFlow增加了对预生产环境和生产环境的管理,即Master分支对应为开发环境的分支,预生产和生产环境由其他分支(如Pre-Production、Production)进行管理。在这种情况下,Master分支是Pre-Production分支的上游,Pre-Production是Production分支的上游;GitLabFlow规定代码必须从上游向下游发展,即新功能或修复Bug时,特性分支的代码测试无误后,必须先合入Master分支,然后才能由Master分支向Pre-Production环境合入,最后由Pre-Production合入到Production。

GitLabFlow中的Merge Request是将一个分支合入到另一个分支的请求,通过Merge Request可以对比合入分支和被合入分支的差异,也可以做代码的Review。
9 . 简述GitHubFlow的分支类型和作用 ?

参考回答:

GitHubFlow看名字也知道和GitHub有关,它来源于GitHub团队的工作实践。当代码托管在GitHub上时,则需要使用GitHubFlow。相比GitFlow而言,GitHubFlow没有那么多分支。

GitHubFlow通常只有一个Master分支是固定的,而且GitHubFlow中的Master分支通常是受保护的,只有特定权限的人才可以向Master分支合入代码。

在GitHubFlow中,新功能开发或修复Bug需要从Master分支拉取一个新分支,在这个新分支上进行代码提交;功能开发完成,开发者创建Pull Request(简称PR),通知源仓库开发者进行代码修改review,确认无误后,将由源仓库开发人员将代码合入Master分支。
很多人可能会问,提交代码通常是commit或者push,拉取代码才是pull,为什么GitHubFlow中提交代码提出的是"Pull Request"。因为在GitHubFlow中,PR是通知其他人员到你的代码库去拉取代码至本地,然后由他们进行最终的提交,所以用"pull"而非"push"。

GitHubFlow优点是相对于GitFlow来说比较简单,其缺点是因为只有一条Master分支,万一代码合入后,由于某些因素Master分支不能立刻发布,就会导致最终发布的版本和计划不同。
10 . 简述Git Flow的分支类型和作用 ?

参考回答:

GitFlow是这三种分支策略中最早出现的。

GitFlow通常包含五种类型的分支:Master分支、Develop分支、Feature分支、Release分支以及Hotfix分支。

Master分支:主干分支,也是正式发布版本的分支,其包含可以部署到生产环境中的代码,通常情况下只允许其他分支将代码合入,不允许向Master分支直接提交代码(对应生产环境)。
Develop分支:开发分支,用来集成测试最新合入的开发成果,包含要发布到下一个Release的代码(对应开发环境)。
Feature分支:特性分支,通常从Develop分支拉出,每个新特性的开发对应一个特性分支,用于开发人员提交代码并进行自测。自测完成后,会将Feature分支的代码合并至Develop分支,进入下一个Release。
Release分支:发布分支,发布新版本时,基于Develop分支创建,发布完成后,合并到Master和Develop分支(对应集成测试环境)。
Hot fix分支:热修复分支,生产环境发现新Bug时创建的临时分支,问题验证通过后,合并到Master和Develop分支。
11 . 简述Git常见的分支策略?

参考回答:

常见的分支策略有以下三种:GitFlow、GitHubFlow以及GitLabFlow
12 . 简述如何在Git中创建存储库?

参考回答:

要创建存储库,先为项目创建一个目录(如果该目录不存在),然后运行命令 git init。通过运行此命令,将在项目的目录中创建 .git 目录。
13 . 简述Git提交对象包含什么?

参考回答:

Commit 对象包含以下组件,你应该提到以下这三点:
1 一组文件,表示给定时间点的项目状态
2 引用父提交对象
3 SHAI 名称,一个40个字符的字符串,提交对象的唯一标识
14 . 如何找到Git特定提交中已更改的文件列表?

参考回答:

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

参考回答:

删除或修复新提交中的错误文件,并将其推送到远程存储库。这是修复错误的最自然方式。对文件进行必要的修改后,将其提交到我将使用的远程存储库
git commit -m "commit message"
创建一个新的提交,撤消在错误提交中所做的所有更改。可以使用命令:
git revert
16 . Git 是用什么语言编写的?

参考回答:

Git使用 C 语言编写。 GIT 很快,C 语言通过减少运行时的开销来做到这一点。
17 . 简述Git和SVN有什么区别?

参考回答:

1、定义不同
svn:Apache Subversion是Apache许可证下的开源软件版本和版本控制系统。
git:Git是由Linus Torvalds在2005年开发的开源分布式版本控制系统。它强调速度和数据完整性。
2、模型类型不同
svn:svn是集中式模型。
git:Git 是一个分布式模型。
3、存储单元不同
svn:SVN按照原始文件存储,体积较大。SVN是按文件所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。
git:Git按照元数据方式存储,体积很小,GIT把内容按元数据方式存储,如果你把.git目录的体积大小跟.svn比较,你会发现它们差距很大。因为,.git目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。
4、是否拥有全局版本号
Git没有一个全局版本号,而SVN有------目前为止这是跟SVN相比Git缺少的最大的一个特征。
5、内容完整性不同
Git的内容的完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
6、版本库不同
svn:SVN只能有一个指定中央版本库。当这个中央版本库有问题时,所有工作成员都一起瘫痪直到版本库维修完毕或者新的版本库设立完成。
git:Git可以有无限个版本库。或者,更正确的说法,每一个Git都是一个版本库,区别是它们是否拥有活跃目录(Git Working Tree)。如果主要版本库发生了什么事,工作成员仍然可以在自己的本地版本库(local repository)提交,等待主要版本库恢复即可。工作成员也可以提交到其他的版本库。
7、克隆目录速度不同
克隆一份全新的目录以同样拥有五个分支来说,git要快于svn,SVN是同时复制5个版本的文件,也就是说重复五次同样的动作。而Git只是获取文件的每个版本的元素,然后只载入主要的分支(master),克隆一个拥有将近一万个提交(commit),五个分支,每个分支有大约1500个文件的 SVN,耗了将近一个小时,而Git只用了区区的1分钟!
8、分支不同
svn:分支在SVN中一点不特别,就是版本库中的另外的一个目录。如果你想知道是否合并了一个分支,你需要手工运行像这样的命令svn propget svn:mergeinfo,来确认代码是否被合并。
git:处理GIT的分支却是相当的简单和有趣。你可以从同一个工作目录下快速的在几个分支间切换。你很容易发现未被合并的分支,你能简单而快捷的合并这些文件。
9、创建目录不同
svn:在SVN中,我们在每个文件夹中创建.svn目录。
git:在 git 中,我们只创建 .git 目录。
10、特点不同
svn:
目录已版本控制
复制、删除和重命名。
自由格式的版本化元数据 。
原子提交。
分支和标记。
合并跟踪。
文件锁定。
git:
分布式系统。
分支。
兼容性。
非线性开发。
轻。
开源。
18 . 解释Git中的"staging area"或"index"是什么?

参考回答:

代码在完成提交之前,可以在称为"staging area"或"index"的中间区域中对其进行格式化和审查。从图中可以看出,每个更改首先在暂存区域中进行验证,我将其称为"stage file",然后将更改提交到存储库。
19 . 详细阐述git merge命令 ?

参考回答:

git merge命令用于将两个或两个以上的开发历史加入(合并)一起。
使用语法
git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
[-s ] [-X ] [-S[]]
[--[no-]allow-unrelated-histories]
[--[no-]rerere-autoupdate] [-m ] [...​]
git merge --abort
git merge --continue
Shell
描述将来自命名提交的更改(从其历史从当前分支转移到当前分支之后)。 该命令由git pull用于合并来自另一个存储库的更改,可以手动使用将更改从一个分支合并到另一个分支。
示例以下是一些示例 -
示例-1
合并分支fixes和enhancements在当前分支的顶部,使它们合并:
$ git merge fixes enhancements
Shell
示例-2
合并obsolete分支到当前分支,使用ours合并策略:
$ git merge -s ours obsolete
Shell
示例-3
将分支maint合并到当前分支中,但不要自动进行新的提交:
$ git merge --no-commit maint
Shell
当您想要对合并进行进一步更改时,可以使用此选项,或者想要自己编写合并提交消息。应该不要滥用这个选项来潜入到合并提交中。小修补程序,如版本名称将是可以接受的。
示例-4
将分支dev合并到当前分支中,自动进行新的提交:
//更多请阅读:https://www.yiibai.com/git/git_merge.html
20 . 简述 Git clone指定分支操作 ?

参考回答:

git clone 不指定分支
git clone http://10.1.1.11/service/tmall-service.git
git clone 指定分支
git clone -b dev_jk http://10.1.1.11/service/tmall-service.git
需要注意-b branch_name在https地址之前
21 . Git撤销commit但是未git push的情况?

参考回答:

找到上次git commit的id
git log//查看列表里的内容并直接复制commit id
情况一:执行撤销操作,同时将代码恢复到该commit_id之前的代码提交状态
git reset --hard commit_id
情况二:完成commit命令的撤销,但是不对代码修改进行撤销,可以直接通过git commit 重新提交对本地代码的修改
git reset commit_id
22 . 简述Git在pull后想要回滚到之前版本?

参考回答:

git reflog master (查看本地master分支历史变动纪录)
使用git reset --hard (恢复到之前位置)
或git reset --hard master@{1}
23 . 简述Git在pull后想要回滚到之前版本?

参考回答:

git reflog master (查看本地master分支历史变动纪录)
使用git reset --hard (恢复到之前位置)
或git reset --hard master@{1}
24 . 简述Git如何强制切换至其他分支 ?

参考回答:

强制切换分支

git checkout -f develop
//Git 一个分支完全替换成另一个分支
git checkout master//切换到旧分支
git reset --hard develop//将本地的旧分支master重置为develop
git push origin master --force//在推送到远程仓库
25 . 简述git rm与rm的区别 ?

参考回答:

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 "Changes not staged for commit" 部分(也就是 未暂存清单)看到:
$ rm PROJECTS.md
$ git status On branch master Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory) deleted: PROJECTS.md no changes added to commit (use "git add" and/or "git commit -a")
然后再运行 git rm 记录此次移除文件的操作:
$ git rm PROJECTS.md rm 'PROJECTS.md'
$ git status On branch master Your branch is up-to-date with 'origin/master'.
Changes to be committed: (use "git reset HEAD ..." to unstage)
deleted: PROJECTS.md
下一次提交时,该文件就不再纳入版本管理了。 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:
$ git rm --cached README
git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比如:
$ git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:
$ git rm \*~
该命令会删除所有名字以 ~ 结尾的文件。
26 . 请问什么情况下使用"git rebase"代替"git merge"?

参考回答:

这两个命令都是把修改从一个分支集成到另一个分支上,它们只是以非常不同的方式进行。 考虑一下场景,在合并和变基前:

A <- B <- C [master]
^
\
D <- E [branch]
在 git merge master 之后:

A <- B <- C
^ ^
\ \
D <- E <- F
在 git rebase master 之后:

A <- B <- C <- D <- E
使用变基时,意味着使用另一个分支作为集成修改的新基础。

何时使用:
如果你对修改不够果断,请使用合并操作。
根据你希望的历史记录的样子,而选择使用变基或合并操作。
更多需要考虑的因素:
分支是否与团队外部的开发人员共享修改(如开源、公开项目)?如果是这样,请不要使用变基操作。变基会破坏分支,除非他们使用 git pull --rebase,否则这些开发人员将会得到损坏的或不一致的仓库。
你的开发团队技术是否足够娴熟?变基是一种破坏性操作。这意味着,如果你没有正确使用它,你可能会丢失提交,并且/或者会破坏其他开发者仓库的一致性。
分支本身是否代表有用的信息?一些团队使用功能分支(branch-per-feature)模式,每个分支代表一个功能(或错误修复,或子功能等)。在此模式中,分支有助于识别相关提交的集合。在每个开发人员分支(branch-per-developer)模式中,分支本身不会传达任何其他信息(提交信息已有作者)。则在这种模式下,变基不会有任何破坏。
是否无论如何都要还原合并?恢复(如在撤销中)变基,是相当困难的,并且/或者在变基中存在冲突时,是不可能完成的。如果你考虑到日后可能需要恢复,请使用合并操作。
27 . 解释什么时候应使用 "git stash"?

参考回答:

git stash 命令把你未提交的修改(已暂存(staged)和未暂存的(unstaged))保存以供后续使用,以后就可以从工作副本中进行还原。
$ git status
On branch master
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
$ git stash
Saved working directory and index state WIP on master: 5002d47 our new homepageHEAD is now at 5002d47 our new homepage
$ git statusOn branch masternothing to commit, working tree clean
我们可以使用暂存(stash)的一个地方是,如果我们发现在上次提交中忘记了某些内容,并且已经开始在同一分支中处理下一个提交了:
# Assume the latest commit was already done# start working on the next patch, and discovered I was missing something # stash away the current mess I made$ git stash save # some changes in the working dir # and now add them to the last commit:$ git add -u$ git commit --ammend # back to work!$ git stash pop
28 . 解释下 Gitflow 工作流程 ?

参考回答:

Gitflow 工作流程使用两个并行的、长期运行的分支来记录项目的历史记录,分别是 master 和 develop 分支。

Master,随时准备发布线上版本的分支,其所有内容都是经过全面测试和核准的(生产就绪)。

Hotfix,维护(maintenance)或修复(hotfix)分支是用于给快速给生产版本修复打补丁的。修复(hotfix)分支很像发布(release)分支和功能(feature)分支,除非它们是基于 master 而不是 develop 分支。

Develop,是合并所有功能(feature)分支,并执行所有测试的分支。只有当所有内容都经过彻底检查和修复后,才能合并到 master 分支。

Feature,每个功能都应留在自己的分支中开发,可以推送到 develop 分支作为功能(feature)分支的父分支。
29 . Git 中 HEAD、工作树和索引之间的区别?

参考回答:

该工作树/工作目录/工作空间是你看到和编辑的(源)文件的目录树。
该索引/中转区(staging area)是个在 /.git/index,单一的、庞大的二进制文件,该文件列出了当前分支中所有文件的 SHA1 检验和、时间戳和文件名,它不是个带有文件副本的目录。
HEAD是当前检出分支的最后一次提交的引用/指针。
30 . 解释 Forking 工作流程的优点 ?

参考回答:

Forking 工作流程 与其他流行的 Git 工作流程有着根本的区别。它不是用单个服务端仓库充当"中央"代码库,而是为每个开发者提供自己的服务端仓库。Forking 工作流程最常用于公共开源项目中。

Forking 工作流程的主要优点是可以汇集提交贡献,又无需每个开发者提交到一个中央仓库中,从而实现干净的项目历史记录。开发者可以推送(push)代码到自己的服务端仓库,而只有项目维护人员才能直接推送(push)代码到官方仓库中。

当开发者准备发布本地提交时,他们的提交会推送到自己的公共仓库中,而不是官方仓库。然后他们向主仓库提交请求拉取(pull request),这会告知项目维护人员有可以集成的更新
相关推荐
LCG元7 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
high20118 小时前
【Git】-- 版本说明
git
kaixin_learn_qt_ing9 小时前
git clone
git
sin22019 小时前
git stash
git
喝鸡汤9 小时前
一起学Git【第二节:创建版本库】
git
慢慢成长的码农9 小时前
git 同步分支操作
git
sin22019 小时前
git推送本地仓库到远程(Gitee)
git·gitee
丁总学Java11 小时前
git branch -r(--remotes )显示你本地仓库知道的所有 远程分支 的列表
git
GISer_Jing11 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_7482455211 小时前
吉利前端、AI面试
前端·面试·职场和发展