本文节选自《Jump Start Git》一书,该书免费提供给 SitePoint Premium 会员。实体书在全球各大书店有售,您也可以在此处订购。希望您喜欢并能从中受益!
第一章中,我曾谈到自己最初对在项目中尝试新事物的恐惧。如果尝试一些雄心勃勃的功能,却破坏了之前正常运行的部分,该怎么办?Git 的分支功能完美解决了这个问题。
要点总结
git branch [分支名称]
。切换到该分支使用 git checkout [分支名称]
。删除分支使用 git branch -D [分支名称]
,但建议除非必要,否则不要删除分支。git merge [分支名称]
。但是,这可能会在项目历史记录中创建循环,这在大型团队中可能难以导航。下一章将探讨一种不创建循环的合并方法。什么是分支?
在项目中创建一个新分支,本质上意味着创建该项目的副本。您可以使用此副本进行实验,而不会影响原始项目。因此,如果实验失败,您可以放弃它并返回到原始项目——主分支。
但如果实验成功,Git 可以轻松地将实验性元素合并到主分支中。而且,在后期,如果您改变主意,可以轻松地恢复到合并之前的项目状态。
因此,Git 中的分支是独立的开发路径。您可以在分支中创建新的提交,而不会影响其他分支。分支的易用性是 Git 最好的特性之一。(虽然其他版本控制选项(如 CVS)也有分支选项,但在 CVS 上合并分支的体验非常繁琐。如果您有使用其他版本控制系统中分支的经验,请放心,在 Git 中使用分支是完全不同的。)
在 Git 中,您默认处于主分支。名称“master”(主)并不意味着它在任何方面都优越。这只是一个约定俗成的叫法。
注意:分支约定
虽然您可以自由地使用不同的分支作为 Git 中的基础分支,但人们通常期望在主分支中找到特定项目的最新代码。
您可能会争辩说,由于能够返回到任何提交,因此不需要分支。但是,想象一下,您需要向您的主管展示您的工作,同时还要开发一个不属于您已完成工作的新功能的情况。由于分支用于分离不同的想法,因此它使存储库中的代码易于理解。此外,分支使您能够仅在主分支或主分支中保留重要的提交。
分支的另一个用途是它们使您能够同时处理多件事情,而不会相互干扰。假设您提交了功能 1 以供审核,但您的主管需要一些时间才能审核它。同时,您需要处理功能 2。在这种情况下,分支就派上用场了。如果您在新分支上处理您的新想法,您可以随时切换回您之前的分支,以将存储库恢复到之前的状态,该状态不包含与您的想法相关的任何代码。
现在让我们开始在 Git 中使用分支。要查看分支列表和您正在使用的当前分支,请运行以下命令:
<code>git branch</code>
如果您已克隆您的存储库或设置了远程存储库,您也可以看到远程分支。只需在上述命令后添加 -a:
<code>git branch -a</code>
如上所示,红色分支表示它们位于远程存储库。在我们的例子中,我们可以看到 origin 远程存储库中存在的各种分支。
创建分支
在 Git 中创建分支有多种方法。要创建一个新分支并保留在当前分支中,请运行以下命令:
<code>git branch test_branch</code>
这里,test_branch
是创建的分支的名称。但是,运行 <code>git branch</code> 后,似乎活动分支仍然是主分支。要更改活动分支,我们可以运行 checkout 命令(如下所示):
<code>git checkout test_branch</code>
您还可以组合上述两个命令,从而通过在 checkout 命令后添加 -b 来在一个命令中创建和检出新分支:
<code>git checkout -b new_test_branch</code>
我们刚刚创建的分支基于当前活动分支(在本例中为主分支)的最新提交。如果您想基于某个提交(例如 cafb55d
)创建分支(例如 old_commit_branch
),您可以运行以下命令:
<code>git checkout -b old_commit_branch cafb55d</code>
要将当前分支重命名为 renamed_branch
,请运行以下命令:
<code>git branch -m renamed_branch</code>
删除分支
要删除分支,请运行以下命令:
<code>git branch</code>
注意:除非必须,否则不要删除分支
由于保留分支实际上没有任何缺点,因此我建议除非存储库中的分支数量变得太大而难以管理,否则不要删除它们。
上面使用的 -D
选项即使分支尚未与远程分支同步,也会删除分支。这意味着,如果您的当前分支中有尚未推送的提交,-D
仍然会删除您的分支,而不会发出任何警告。为了确保您不会丢失数据,您可以使用 -d
作为 -D
的替代项。-d
仅在分支已与远程分支同步时才删除分支。由于我们的分支尚未同步,让我们看看如果我们使用 -d
会发生什么,如下所示:
如您所见,Git 会向您发出警告并中止操作,因为数据尚未与分支合并。
分支和 HEAD
既然我们有机会尝试分支的基础知识,那么让我们花一点时间讨论分支在 Git 中的工作方式,并介绍一个重要的概念:HEAD。
如上所述,分支只是不同提交之间的链接,或者说是通过提交的路径。需要注意的是,在使用分支时,分支的 HEAD 指向分支中的最新提交。我将在接下来的章节中多次提到 HEAD。在 Git 中,HEAD 指向分支中的最新提交。换句话说,它指的是分支的顶端。
分支本质上是指向提交的指针,该提交具有父提交、祖父母提交等等。这个提交链形成了我上面提到的路径。那么,如何链接分支和 HEAD 呢?好吧,HEAD 和当前分支的顶端指向相同的提交。让我们来看一个图表来说明这个想法:
如上所示,branch_A
最初是活动分支,HEAD 指向提交 C。提交 A 是基础提交,没有任何父提交,因此 branch_A
中的提交按时间反向顺序排列(这也构成了我上面谈到的路径)是 C → B → A。branch_B
中的提交是 E → D → B → A。HEAD 指向活动分支 branch_A
的最新提交,即提交 C。当我们添加提交时,它将添加到活动分支。提交后,branch_A
指向 F,分支遵循 F → C → B → A,而 branch_B
保持不变。HEAD 现在指向提交 F。同样,当我们添加另一个提交时,更改在图中得到演示。
高级分支:合并分支
如前所述,Git 最大的优势之一是合并分支特别容易。现在让我们看看它是如何完成的。
我们将创建两个新分支——new_feature
和 another_feature
——并添加一些虚拟提交。检查每个分支的历史记录向我们显示,another_feature
分支领先一个提交,如下所示:
这种情况可以如下图所示。每个圆圈代表一个提交,分支名称指向其 HEAD(分支的顶端)。
要将 new_feature
与主分支合并,请运行以下命令(首先确保主分支处于活动状态):
<code>git branch</code>
结果可以如下图所示:
要将 another_feature
与 new_feature
合并,只需运行以下命令(确保 new_feature
分支处于活动状态):
<code>git branch -a</code>
结果可以如下图所示:
重要提示:注意循环
上图显示此合并在您的项目历史记录中跨两个提交创建了一个循环,其中工作流分别发散和收敛。在单独工作或在小型团队中工作时,此类循环可能不是问题。但是,在一个更大的团队中——自从您偏离主分支以来可能有很多提交——这种大型循环使得难以导航历史记录并理解更改。我们将在第 6 章中探讨使用 rebase 命令合并分支而不创建循环的方法。
此合并没有任何“冲突”。原因很简单,与 another_feature
分支相比,没有新的提交添加到 new_feature
分支。Git 中的冲突发生在同一文件的同一部分在两个分支中的非公共提交中都被修改时。Git 会引发冲突以确保您不会丢失任何数据。
我们将在下一章详细讨论冲突。我前面提到过,分支可以通过简单的提交路径来可视化。当我们合并分支并且没有冲突时,例如上面那样,只有分支路径发生更改,并且分支的 HEAD 会更新。这称为快速前进类型的合并。
合并分支的另一种方法是非快速前进合并,方法是在合并命令后添加 --no-ff
。通过这种方式,将在基础分支上创建一个新的提交,其中包含来自另一个分支的更改。您还需要指定提交消息:
<code>git branch</code>
在上面的示例中,前者(将 new_feature
与主分支合并)是快速前进合并,而后者是非快速前进合并,带有合并提交。
虽然快速前进样式的合并是默认的,但通常最好对合并到主分支的合并使用非快速前进方法。从长远来看,标识新功能合并的新提交可能是有益的,因为它将负责新功能的代码部分逻辑地分离到一个提交中。
结论
您学到了什么?
在本章中,我们讨论了什么是分支以及如何在 Git 中管理它们。我们研究了创建、修改、删除和合并分支。
接下来是什么?
我已经谈到 Git 如何对团队合作的开发人员有益。下一章将更详细地探讨这一点,以及在分布式团队中经常使用的特定 Git 操作和命令。
关于 Git 分支的常见问题
Git 分支是一个强大的功能,允许开发人员创建单独的开发线路。这在处理新功能或修复程序时尤其有用,因为它允许您将工作与主项目隔离开来。功能或修复程序完成后并经过测试后,可以将其合并回主项目。这确保了主项目保持稳定,并允许多个开发人员同时处理不同的功能而不会相互干扰。
在 Git 中创建新分支很简单。您可以使用 <code>git branch</code> 命令,后跟新分支的名称。例如,git branch new_feature
将创建一个名为“new_feature”的新分支。要切换到此分支,您可以使用 git checkout
命令,如下所示:git checkout new_feature
。
在 Git 中合并分支使用 git merge
命令。在合并之前,您需要位于要合并到的分支上。例如,如果您想将名为“new_feature”的分支合并到“master”分支,您首先需要使用 git checkout master
切换到主分支,然后使用 git merge new_feature
命令。
Git 分支指针是一个包含其指向的提交的 SHA1 哈希的文件。当您创建新分支时,Git 会创建一个新的指针,并随着您进行的每次新提交一起移动它。这允许 Git 跟踪项目的历史记录。
在 Git 中删除分支使用 git branch -d
命令,后跟分支的名称。例如,git branch -d old_feature
将删除名为“old_feature”的分支。但是,如果分支有尚未合并到另一个分支中的提交,Git 将阻止您删除分支。要强制删除,您可以使用 -D
选项。
当从当前分支尖端到目标分支存在线性路径时,Git 中的快速前进合并是可能的。Git 不创建新的提交,而是将当前分支指针向上移动到目标分支。另一方面,当不存在线性路径时,使用三方合并。Git 将创建一个具有两个父级的新的提交,有效地连接两个分支。
您可以使用不带参数的 <code>git branch</code> 命令查看 Git 存储库中的所有分支。这将列出所有本地分支。如果您还想查看远程分支,可以使用 -a
选项,如下所示:<code>git branch -a</code>。
在 Git 中重命名分支使用 git branch -m
命令,后跟旧名称和新名称。例如,git branch -m old_name new_name
将将分支“old_name”重命名为“new_name”。
Git 中的分离 HEAD 发生在您检出提交而不是分支时。这可能很危险,因为当您检出到另一个分支时,您所做的任何更改都将丢失。为避免这种情况,请务必始终检出到分支,而不是提交。
在 Git 中合并分支时,如果同一文件的同一部分在两个分支中都被修改,则可能会发生冲突。Git 将标记该文件为“未合并”,您需要手动解决冲突。您可以通过在文本编辑器中打开文件,找到冲突标记(<<<<<<<
),并决定保留哪些更改来执行此操作。解决所有冲突后,您可以使用 git add
添加文件,然后使用 git commit
提交它。
以上是快点开始git:在git中分支的详细内容。更多信息请关注PHP中文网其他相关文章!