前言
本文介绍了Git的紧张功能之一——分支。从分支的概念引入,介绍了管理分支的命令,通过举例的方式使其更为直观,更易明确。
一、分支的概念
1. 分支是什么?
分支是Git自己具备的紧张功能之一。在Git中,分支是轻量级的,易于创建、归并和删除。每一个分支都具有独立的开辟情况,使得开辟者们可以在不同的分支上举行不同的开辟任务,而不会相互影响。当支线分支上的任务开辟完毕可以统一归并到主分支中,有益于维护主分支的稳定性。
讲个故事资助明确这个概念:
小明是一个超本领者,他的超本领是分身术,他可以分身出多个自己,在同一个时间做不同的事情。他先创造出自己的分身A,安排A去学习C++编程,再分身出分身B去学习JAVA…,当分身完成学习后,再将分身召唤回自己的体内,终极小明就学习到了所有分身学习到的内容。
在这个故事中,小明本体就是主分支,他的不同分支则是支线分支,这些分支举行的任务不会影响到主分支,也不会相互影响,终极都可以归并到主分支。
在之前的文章中,我们并没有涉及到分支的内容,所有的操作都是在一条分支上举行的,这条分支就是我们创建Git堆栈时,Git主动帮我们生成的master分支(也就是主分支)。
2. 为什么要使用分支?
假如没有分支,那么我们就需要在一条提交线上,也就是master分支上举行所有的开辟,举行开辟的分支可能会出现各种的bug,会导致master分支不稳定,无法向用户提供一个稳定的使用版本。因此,使用分支可以在一定程度上保证master分支的稳定性。
其次,使用分支可以支持多人同时开辟一个项目,缩短了开辟的时间成本。
二、命令
1. git branch
- git branch #查看当前所有分支
- git branch dev #创建dev分支
- git branch -d dev #删除dev分支
- git branch -D dev #强制删除dev分支
复制代码
我们检察.git目录,可以看到.git/refs/heads下已经多出了一个dev的文件
由于dev分支是基于master分支创建的,因此它的最新提交是在master上创建dev分支时的最新提交
可以参考下面的时间线图:
当dev分支对于我们就没有用时,可以使用git branch -d dev命令将dev分支删除。需要注意的是,不能删除当前所处的分支:
可以参考下面的时间线图:
2. git checkout
- git checkout dev #切换到dev分支
- git checkout -b dev #创建新分支dev,并切换到dev分支
复制代码
在之前的文章中,提到过HEAD是指向master分支的指针,实在严格来讲,HEAD是指向当前分支的指针,因为我们并没有创建其他分支,所以HEAD就是指向master分支。
现在我们新建了dev分支,而且将当前分支切换为dev,此时再检察HEAD可以发现它是指向当前分支——dev分支,这说明我们已经成功切换到了dev分支上:
可以参考下面的时间线图:
我们可以对dev分支上的代码举行修改以及add/commit:
如图,可以看到我们已经将对code1文件的修改提交到了版本库。
现在将分支切换回master,检察我们对code1文件的修改:
可以发现,master分支上并没有我们在dev上提交的修改,再次切换回dev分支,检察修改内容是否丢掉了:
当我们将当前分支切换回dev分支时,再检察code1文件,发现我们的修改还在,这是什么原因呢?
我们可以看看当前dev分支和master分支的指向,会发现两者此时指向提交是不同的:
这是因为我们的提交操作是在dev分支上举行的,而master分支此时的最新提交并没有变化,可以参考下面的时间线图:
当切换回master分支时,HEAD就指向了master,自然看不到dev的提交了
3. git merge
假如,我们需要将dev分支的提交内容同步到master分支,就需要用到分支归并的功能,下面的git merge命令就是用于归并分支:
- git merge dev #合并指定分支dev到当前分支
复制代码 要将dev分支上的提交归并到master分支上,需要先切换到master分支,再实行git merge命令,如图所示:
可以看到实行git merge命令后,会出现一个fast forward提示信息。fast forward是快进模式,本质是简朴的将目的分支master的指针移动到源分支dev的最新提交位置。所以归并的速度非常快,但是并非每次的归并都是fast forward模式。
可以参考下面的时间线图:
Fast-forward(快进)模式是Git中用于归并分支的一种计谋。这种模式下,将源分支的代码归并到目的分支,假如目的分支(通常是主分支,如master)的最新提交是源分支(如feature或bug-fix分支)的祖先,那么归并操作会简朴地将目的分支的指针向前移动到源分支的最新提交位置。这意味着归并是通过“快进”指针来完成的,而不是创建一个新的归并提交。
以下是Fast-forward模式归并的关键点:
- 归并条件:Fast-forward归并实用于源分支的最新提交是目的分支的直接后代的情况。换句话说,目的分支的所有提交都在源分支中存在,大概目的分支自源分支分离以来没有新的提交。
- 归并过程:在Fast-forward归并中,目的分支的指针直接移动到源分支的最新提交,没有实际的归并操作发生。因此,归并后的提交历史记录看起来就像是源分支的提交直接在目的分支上举行了提交。
- 优点:Fast-forward归并的优点在于它的简朴性和高效性。由于不需要创建新的归并提交,归并过程非常快速,而且提交历史记录保持线性,易于明确和追踪。
- 缺点:然而,Fast-forward归并也有其局限性。它不会在提交历史记录中留下归并发生的记录,这意味着一旦归并完成,就无法从提交历史中看出两个分支曾经归并过。这对于需要保留完备分支历史记录的团队来说可能是一个缺点。
- 如何避免Fast-forward归并:假如希望在归并时总是创建一个新的归并提交,可以使用--no-ff选项。如许归并时会强制创建一个新的归并提交(纵然可以实行Fast-forward归并)。
总的来说,Fast-forward模式是一种简朴且高效的分支归并计谋,实用于那些希望保持线性提交历史记录的场景。然而,在需要保留分支归并信息的情况下,可能需要思量使用其他归并计谋,如--no-ff模式或Rebase。
假如归并的分支和当前的分支又冲突,则会提示归并失败,某文件内有冲突。
进入该文件检察,Git会用<<<<<<<, =======, >>>>>>>来将不同分支之间冲突的内容标志出来,<<<<<<<和=======之间的是当前分支的内容,=======和>>>>>>>之间的是指定要归并分支的内容。
解决归并冲突,需要程序员自行决定是留下两个分支冲突内容的哪一个(删除扬弃的谁人分支的内容,并将<<<<<<<, =======, >>>>>>>符号也删除),大概都留下(只删除<<<<<<<, =======, >>>>>>>符号)。然后需要add这次的修改,并commit到版本库才算归并完成。
举例:
在dev1分支修改code2文件,并commit到版本库,同时在master分支对code2文件举行修改,也commit到版本库。再实行git merge命令将dev1分支归并到master分支:
可以参考下面的时间线图:
注意:修改完冲突代码后一定要再次提交修改后的效果!!!
在fast forward模式(简写为ff)下,我们归并到主分支后,检察提交记录(使用命令git log --graph --abbrev-commit),无法看出该提交是merge的支线分支还是主分支自己提交的。
而在归并时发生冲突,我们解决冲突后,会再实行一次新的提交,这种就不是fast forward模式(可以称之为no fast forward模式,简写为no-ff),检察提交记录,可以看出该提交是支线分支merge到主分支的。
可以看出在no fast forward模式下举行merge,对我们后续检察提交历史记录是有很大资助的(可以直观检察到是谁人分支的开辟任务终极归并到主分支,假如代码出现bug也方便定位到详细开辟项目以及开辟人员)。
Git是支持我们强制禁用fast forward模式的,当merge的时间会生成一个新的commit,便于我们从历史提交中检察到分支信息。
- git merge --no-ff -m "merge on no-ff" dev #在no-ff模式下合并分支dev到当前分支
复制代码 三、分支管理
由于在Git上创建、归并和删除分支都非常快,所以Git鼓励使用分支完成某个任务,归并后再删除分支。如许和在master分支上工作效果是一样的,但是过程更安全。接下来简朴了解几个git分支在实际应用中的计谋方法。
1. 分支计谋
在实际开辟中,master分支都需要是非常稳定的版本,通常只能用于发布新版本,所以,不能直接在master分支上举行开辟。我们一般是在基于master分支创建的feature分支/fix-bug分支上举行开辟,开辟结束后,由测试人员来对我们分支的代码举行测试,确定没有问题后才会将我们的分支归并到master分支上。
因此,团队合作的分支可以看作下面的图:
2. bug分支
假如,我们目前在dev1分支上举行新功能开辟,开辟了一部门后,发现master分支上存在bug需要解决,但是当前工作区中的dev1的代码只开辟了一部门,还不能提交,怎么办?
Git提供了git stash命令,它可以将当前工作区中的修改储藏,被储藏的内容可以在将来某个时刻被规复
git stash
注意:git stash只能储藏被git跟踪的文件(即,在之前的操作中被git命令add/commit的文件,假如是本次修改新创建的文件则无法被该命令储藏)
再用git status命令检察工作区就是干净的,因此可以放心的切换分支来修复bug。由于我们要基于master分支修复bug,因此需要切回到master分支,新建暂时分支来修复bug:
修复完成后,再切回master分支,归并fix-bug分支,末了再将fix-bug分支删除。
至此,修复bug的工作就已经完成了,我们需要继承回到dev1分支举行功能开辟。
先切换回dev1分支,此时的工作区是干净的,我们需要通过git stash命令将刚刚储藏内容规复:
- git stash list #查看stash储藏的列表
- git stash pop #恢复最近一次stash储藏的内容,同时将这次stash从储藏列表中删除
- git stash apply #恢复指定stash内容, 恢复后对应stash并不删除
- git stash drop #删除指定stash内容, 可以和上面的 git stash apply 配套使用,先恢复内容,再删除stash。
复制代码
我们发现在暂时分支上修复的bug,虽然归并到master分支,但是我们的dev1分支上没有这次提交。
可以参考如下时间线图:
此时,master分支最新的提交,是领先于创建dev1分支时master分支的最新提交的。因此,我们在dev1分支中是不能检察到修复bug的代码。
我们在dev1分支上提交的代码,终极也是需要归并到master分支上的。在前面文章中,我们是先切换到master分支,然后使用merge归并分支,但是,如许做会有一定风险。
我们在归并分支时可能会出现冲突,而归并冲突是需要我们举行手动解决的,我们无法确保对于冲突问题可以一次性正确的解决掉(在实际开辟过程中,产生的归并冲突可能会有几十上千行,需要和其他开辟同事协商处置惩罚,在解决的过程中也可能手误堕落,终极会导致归并到master分支上的代码有问题),导致master分支不稳定。
因此,我们最好是先在自己的分支上归并master分支,然后再让master分支归并dev1分支。如许即便产生冲突,也可以在本地分支解决并举行测试,不会影响到master分支。
可以参考如下时间线图:
3. 删除暂时分支
前文中,我们举行开辟时会新建一个feature分支,当我们完成开辟后,将分支的内容归并到master分支后,末了使用git branch -d feature命令将feature分支删除。
但是,假如我们在某个feature分支上开辟了一部门,忽然被通知该功能制止开辟,相当于这部门代码白写了,这个feature分支留着没用也要被删除。
由于我们已经在这个分支上举行了提交,这时使用git branch -d feature命令删除这个分支是不成功的(git会对我们的分支举行一定的保护,当分支还未被归并时,git会认为该分支还有用,不能直接被删除)。
这时就需要使用git branch -D feature命令强制删除feature分支。
举例如下:
总结
以上就是本日要讲的内容,本文介绍了Git分支管理的相关概念。本文作者目前也是正在学习Git相关的知识,假如文章中的内容有错误大概不严谨的部门,欢迎各人在评论区指出,也欢迎各人在评论区提问、交流。
末了,假如本篇文章对你有所开导的话,希望可以多多支持作者,谢谢各人!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |