Git 分支 - 分支的创建与合并

分支的创建

$ git branch <分支名>

与其他文件管理系统相比,Git最大的优势无疑是能够很轻易地就创建出新的分支。同时,当创建出的新分支不再使用时又能够很方便地删除。这一切源于Git创建分支的原理,与其他文件管理系统通过拷贝文件来生成分支不同,Git创建新分支实际上只是创建了一个指向当前commit对象的指针,而分支实质上仅是包含所指对象校验和(长度为 40 的 SHA-1 值字符串)的文件,因此它的创建和销毁都异常高效。 创建一个新分支就相当于往一个文件中写入 41 个字节(40 个字符和 1 个换行符)。

$ git branch release

Git 分支 - 分支的创建与合并_第1张图片
Git 又是怎么知道当前在哪一个分支上呢? 也很简单,它有一个名为 HEAD 的特殊指针。在 Git 中,它是一个指针,指向当前所在的本地分支(译注:将 HEAD 想象为当前分支的别名)。

$ git checkout C2

Git 分支 - 分支的创建与合并_第2张图片
要切换到一个已存在的分支,你需要使用 git checkout 命令。 我们现在切换到新创建的 release分支去:

$ git checkout release

Git 分支 - 分支的创建与合并_第3张图片
HEAD指针指向哪个分支,提交时就会在哪个分支上进行延伸。

$ git commit

Git 分支 - 分支的创建与合并_第4张图片
当使用git checkout 时,要留意你的工作目录和暂存区里那些还没有被提交的修改, 它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。 在你切换分支之前,保持好一个干净的状态。 有两种方法可以解决这个问题,一种是将没提交的修改提交,另一种是通过git stash暂存还没提交的内容到一个栈上,后续可以通过git stash apply将数据还原到原先的位置和状态。

分支合并

当你想合并的分支release所指向的提交是你所在分支提交的后继,Git会将分支的指针往前移。如果顺着一个分支走下去能够到达另一个分支(在同一条路径上),那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。

$ git checkout main
$ git merge release

Git 分支 - 分支的创建与合并_第5张图片
除了位于同一条路径下不同分支的合并,当路径出现分叉,位于不同路径下的分支合并则是完全另一种情况:
Git 分支 - 分支的创建与合并_第6张图片

$ git checkout main
$ git merge release

Git 分支 - 分支的创建与合并_第7张图片

出现分叉后的分支合并这种情况,Git会使用两个分支的末端所指的快照(C4和C5)以及这两个分支的公共祖先(C2),做一个简单的三方合并,合并的结果最终是生成一个新的快照(C6)。

遇到冲突时的分支合并

有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 分支的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:

$ git merge release
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")

Unmerged paths:
(use "git add ..." to mark resolution)

both modified: index.html

no changes added to commit (use "git add" and/or "git commit -a")

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:

<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
please contact us at [email protected]
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 release 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:

<div id="footer">
please contact us at [email protected]
</div>

上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<< , ======= , 和 >>>>>>> 这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。如果你对结果感到满意,并且确定之前有冲突的的文件都已经暂存了,这时你可以输入 git commit 来完成合并提交。

你可能感兴趣的:(git,git)