考考你的 Git 掌握情况
.什么是Git
- Git 是分布式版本控制系统(DVCS)。它可以跟踪文件的更改,并允许你恢复到任何特定版本的更改。
- 与 SVN 等其他版本控制系统(VCS)相比,其分布式架构具有许多优势,一个主要优点是它不依赖于中央服务器来存储项目文件的所有版本。
- 每个开发人员都可以“克隆”我在图中用“Local repository”标注的存储库的副本,并且在他的硬盘驱动器上具有项目的完整历史记录,因此当服务器中断时,你需要的所有恢复数据都在你队友的本地 Git 存储库中。
- 还有一个中央云存储库,开发人员可以向其提交更改,并与其他团队成员进行共享,如图所示,所有协作者都在提交更改“远程存储库”。
.Git和SVN有什么区别?
- Git 是一个分布式的版本控制工具,SVN 是集中版本控制工具
- Git 属于第3代版本控制工具,SVN 则属于第2代版本控制工具
- Git 客户端可以在其本地系统上克隆整个存储库,SVN 的版本历史记录存储在服务器端存储库中
- Git 即使离线也可以提交,SVN 只允许在线提交和回滚
- Git 的Push/pull 操作更快,而 SVN Push/pull 操作较慢
- Git 工程可以用
commit
自动共享,但 SVN 没有任何东西自动共享
. 如何在Git中创建存储库?
要创建存储库,先为项目创建一个目录(如果该目录不存在),然后运行命令 git init。通过运行此命令,将在项目的目录中创建 .git 目录。
. 列举工作中常用的几个git命令?
新增文件的命令:git add file
或者 git add .
提交文件的命令:git commit –m
或者 git commit –a
查看工作区状况:git status –s
拉取合并远程分支的操作:git fetch/git merge
或者 git pull
查看提交记录命令:git reflog
.在 Git 中提交的命令是什么?
用于写入提交的命令是 git commit -a
通过在命令行上加 -a
, 指示 git 提交已修改的所有被跟踪文件的新内容。
如果第一次提交新文件,可以在 git commit -a
之前先 git add <file>
.什么是 Git 复刻(fork)?复刻(fork)、分支(branch)和克隆(clone)之间有什么区别?
复刻(fork):
是对存储仓库(repository)进行的远程的、服务器端的拷贝,从源头上就有所区别。
克隆(clone):
不是复刻,克隆是个对某个远程仓库的本地拷贝。克隆时,实际上是拷贝整个源存储仓库,包括所有历史记录和分支。
分支(branch):
是一种机制,用于处理单一存储仓库中的变更,并最终目的是用于与其他部分代码合并。
.拉取请求(pull request) 和 分支(branch) 之间有什么区别?
分支(branch)
是代码的一个独立版本。
拉取请求(pull request)
是当有人用仓库,建立了自己的分支,做了些修改并合并到该分支(把自己修改应用到别人的代码仓库)。
. git pull 和 git fetch 之间有什么区别?
单来说,git pull
是 git fetch + git merge
。
当你使用 pull
,Git 会试着自动为你完成工作。它是上下文(工作环境)敏感的,所以 Git 会把所有拉取的提交合并到你当前处理的分支中。pull
则是 自动合并提交而没有让你复查的过程。如果你没有细心管理你的分支,你可能会频繁遇到冲突。
当你 fetch
,Git 会收集目标分支中的所有不存在的提交,并将这些提交存储到本地仓库中。但 Git 不会把这些提交合并到当前分支中。这种处理逻辑在当你需要保持仓库更新,在更新文件时又希望处理可能中断的事情时,这将非常实用。而将提交合并到主分支中,则该使用 merge
。
. 描述一下你所使用的分支策略?
- 功能分支(Feature branching)
要素分支模型将特定要素的所有更改保留在分支内。当通过自动化测试对功能进行全面测试和验证时,该分支将合并到主服务器中。 - 任务分支(Task branching)
在此模型中,每个任务都在其自己的分支上实现,任务键包含在分支名称中。很容易看出哪个代码实现了哪个任务,只需在分支名称中查找任务键。 - 发布分支(Release branching)
一旦开发分支获得了足够的发布功能,你就可以克隆该分支来形成发布分支。创建该分支将会启动下一个发布周期,所以在此之后不能再添加任何新功能,只有错误修复,文档生成和其他面向发布的任务应该包含在此分支中。一旦准备好发布,该版本将合并到主服务器并标记版本号。此外,它还应该再将自发布以来已经取得的进展合并回开发分支。
. 分支是否已合并为 master,你可以通过什么手段知道?
git branch –merged
它列出了已合并到当前分支的分支。
git branch –no-merged
它列出了尚未合并的分支。
.新建一个 GIT 功能分支的步骤,提供每个步骤的指令,并对指令进行说明。
Git branch name
创建名字为 name
的 branch
Git checkout xxx_dev
切换到名字为 xxx_dev
的分支
Git pull
从远程分支拉取代码到本地分支
Git checkout -b main_furture_xxx
创建并切换到 main_furture_xxx
Git push origin main_furture_xxx
执行推送的操作,完成本地分支向远程分支的同步
.使用过 git merge 和 git rebase吗?它们之间有什么区别?
简单的说 git merge
和 git rebase
都是合并分支的命令。
git merge branch
会把 branch
分支的差异内容pull到本地,然后与本地分支的内容一并形成一个 committer
对象提交到主分支上,合并后的分支与主分支一致;
git rebase branch
会把 branch
分支优先合并到主分支,然后把本地分支的 commit
放到主分支后面,合并后的分支就好像从合并后主分支又拉了一个分支一样,本地分支本身不会保留提交历史。
. 怎样将 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})"
.在Git中,你如何还原已经 push 并公开的提交?
- 删除或修复新提交中的错误文件,并将其推送到远程存储库。这是修复错误的最自然方式。对文件进行必要的修改后,将其提交到我将使用的远程存储库
git commit -m "commit message
- 创建一个新的提交,撤消在错误提交中所做的所有更改。可以使用命令:
git revert <name of bad commit>
.如果本次提交误操作,如何撤销?
如果想撤销提交到索引区的文件,可以通过 git reset HEAD file
;如果想撤销提交到本地仓库的文件,可以通过 git reset –soft HEAD^n
恢复当前分支的版本库至上一次提交的状态,索引区和工作空间不变更;可以通过 git reset –mixed HEAD^n
恢复当前分支的版本库和索引区至上一次提交的状态,工作区不变更;可以通过 git reset –hard HEAD^n
恢复当前分支的版本库、索引区和工作空间至上一次提交的状态。
. 如何把本地仓库的内容推向一个空的远程仓库?
首先确保本地仓库与远程之间是连同的。如果提交失败,则需要进行下面的命令进行连通:
git remote add origin
远程仓库地址
如果是第一次推送,则进行下面命令:
git push -u origin master
注意:-u 是指定origin为默认主分支
之后的提交,只需要下面的命令:
git push origin master
.Git 中 HEAD、工作树和索引之间的区别?
该工作树/工作目录/工作空间是你看到和编辑的(源)文件的目录树。
该索引/中转区(staging area)是个在 /.git/index,单一的、庞大的二进制文件,该文件列出了当前分支中所有文件的 SHA1 检验和、时间戳和文件名,它不是个带有文件副本的目录。
HEAD是当前检出分支的最后一次提交的引用/指针。
.什么是 Git 中的“裸存储库”?
Git 中的 “裸” 存储库只包含版本控制信息而没有工作文件(没有工作树),并且它不包含特殊的 .git 子目录。相反,它直接在主目录本身包含 .git 子目录中的所有内容,其中工作目录包括:
- 一个 .git 子目录,其中包含你的仓库所有相关的 Git 修订历史记录。
- 工作树,或签出的项目文件的副本。
.你使用过 git stash 命令吗?你一般什么情况下会使用它?
命令git stash
是把工作区修改的内容存储在栈区
以下几种情况会使用到它:
- 解决冲突文件时,会先执行git stash,然后解决冲突;
- 遇到紧急开发任务但目前任务不能提交时,会先执行git stash,然后进行紧急任务的开发,然后通过git stash pop取出栈区的内容继续开发;
- 切换分支时,当前工作空间内容不能提交时,会先执行git stash再进行分支切换。
.如何查看文件的提交历史和分支的提交历史。
使用git log查看文件提交历史 Git log filename
使用git log查看分支提交历史 Git log branch file
.我们在本地工程常会修改一些配置文件,这些文件不需要被提交,而我们又不想每次执行git status时都让这些文件显示出来,我们该如何操作?
在Git工作区的跟目录下创建一个特殊的 .gitignore
文件,然后把忽略的文件名编辑进去,Git就会自动忽略这些文件。
.当GIT出现your-branch-is-ahead-of-origin-master-by-3-commits这一情况时,该如何处理?
Git commit
Git pull
Git push
.使用过git cherry-pick,有什么作用?
命令git cherry-pick可以把branch A的commit复制到branch B上。
在branch B上进行命令操作:
- 复制单个提交:git cherry-pick commitId
- 复制多个提交:git cherry-pick commitId1…commitId3
注意:复制多个提交的命令不包含commitId1.
.如果代码出现 bug, 你们是如何解决的?
创建一个 bug
分支,然后进行bug处理,处理完毕后,合并到 review
分支,组长 review
成功后才能够合并到 master
合并完成之后删除 bug
分支
回到 dev
分支继续开发。
.git rebase的作用?
场景:在公司开发忘记提交到 github
托管,在家里又继续开发新的功能,
然后到公司昨天的代码跟你的新功能合并的时候可以用 git fecth ---> git rebase
那么他的提交记录就不会出现分叉,保持了提交记录的整洁.
.如何做代码的review?
创建 review
分支,然后再创建自己的个人分支,当你完成自己的业务逻辑的时候,
再合并到 review
分支.给组长做代码的 review
.如何查看分支提交的历史记录?查看某个文件的历史记录呢?
查看分支的提交历史记录:
命令 git log –number:
表示查看当前分支前number个详细的提交历史记录;
命令 git log –number –pretty=oneline:
在上个命令的基础上进行简化,只显示sha-1码和提交信息;
命令 git reflog –number:
表示查看所有分支前number个简化的提交历史记录;
命令 git reflog –number –pretty=oneline:
显示简化的信息历史信息;
如果要查看某文件的提交历史记录,直接在上面命令后面加上文件名即可。
注意:如果没有number则显示全部提交次数。
. 提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的?
开发过程中,我们都有自己的特性分支,所以冲突发生的并不多,但也碰到过。诸如公共类的公共方法,我和别人同时修改同一个文件,他提交后我再提交就会报冲突的错误。
发生冲突,在IDE里面一般都是对比本地文件和远程分支的文件,然后把远程分支上文件的内容手工修改到本地文件,
然后再提交冲突的文件使其保证与远程分支的文件一致,这样才会消除冲突,然后再提交自己修改的部分。
特别要注意下,修改本地冲突文件使其与远程仓库的文件保持一致后,需要提交后才能消除冲突,否则无法继续提交。必要时可与同事交流,消除冲突。
发生冲突,也可以使用命令。
- 通过
git stash
命令,把工作区的修改提交到栈区,目的是保存工作区的修改; - 通过
git pull
命令,拉取远程分支上的代码并合并到本地分支,目的是消除冲突; - 通过
git stash pop
命令,把保存在栈区的修改部分合并到最新的工作空间中;
. 解释 Forking 工作流程的优点
Forking
工作流程 与其他流行的 Git 工作流程有着根本的区别。它不是用单个服务端仓库充当“中央”代码库,而是为每个开发者提供自己的服务端仓库。Forking
工作流程最常用于公共开源项目中。
Forking
工作流程的主要优点是可以汇集提交贡献,又无需每个开发者提交到一个中央仓库中,从而实现干净的项目历史记录。开发者可以推送(push)代码到自己的服务端仓库,而只有项目维护人员才能直接推送(push)代码到官方仓库中。
当开发者准备发布本地提交时,他们的提交会推送到自己的公共仓库中,而不是官方仓库。然后他们向主仓库提交请求拉取(pull request),这会告知项目维护人员有可以集成的更新。
. 之前项目中是使用的 Git Flow工作流程吗?它有什么好处?
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的好处
为不同的分支分配一个明确的角色,并定义分支之间如何交互以及什么时间交互;可以帮助大型项目理清分支之间的关系,简化分支的复杂度。