将 Git 分支合并到 Master 的最佳方法
git 最强大的功能之一是分支创建和合并操作。Git 允许用户创建一个新分支并将它们合并到开发代码中。此功能通过鼓励更具体、更小和更精细的任务来改进多个项目的开发流程工作流。
在本教程文章中,我们将讨论将 git 功能分支合并到 master 的不同方法。
git 的主要优点是它的分支系统。GIT 的所有魔力都在这些分支上!主分支将进行所有修改。因此,目标不是直接在这个分支上进行修改,而是在其他分支上进行修改,经过各种测试后,将它们集成到主分支上。
在我们的教程中,为简单起见,我们假设有两个分支,master
分支和称为 feature-1
的特性分支。主分支是包含生产代码的主分支,第二个分支是执行修改或实现新功能的地方。最后,如果一个功能或错误被批准,它将被合并到 master
。
下面开始用一个真实的例子来演示两个分支的合并。首先,我们需要以下内容。
先决条件
在 GitHub 上创建仓库
可以按照 Github 中的介绍创建初始仓库
接下来,使用仓库页面上的添加文件
按钮在 Master 分支上添加两个文件。文件名如下。
file1.txt
file2.txt
在本例中,以下文本内容分别添加到 file1.txt
和 file 2.txt
。
$ cat file1.txt
This is dummy text line 1
This is dummy text line 2
$ cat file2.txt
This is dummy test in 2nd file
克隆仓库
接下来,将你新创建的仓库从 GitHub 克隆到你的系统以创建代码的本地副本。克隆 URL 可以从代码
按钮中检索,如下所示。
使用以下命令进行克隆。
$ git clone git@github.com:project/demorepo.git
克隆成功后,使用以下命令显示并验证 master 分支文件的内容:
$ cat file1.txt
This is dummy text line 1
This is dummy text line 2
$ cat file2.txt
This is dummy test in 2nd file
创建特征分支
$ git branch feature-1
此命令会创建一个新分支,并且不会在 git 上创建新的提交。
检出功能分支
之前,我们使用 git branch feature-1
创建了一个新分支。但是,活动分支是 master
分支。要激活新分支,请在终端中使用以下命令:
$ git checkout feature-1
Switched to branch 'feature-1'
上面的命令会将活动分支从 master
切换到 feature-1
。现在,这个分支已经可以进行单独开发了。
修改功能分支中的文件
我们将在 feature-1
分支中添加一些提交或添加新行。在这种情况下,file2.txt
将在本地修改,然后合并回主分支。
对于到目前为止的更改,我们的提交图如下所示。A 和 E 都代表 master
和 feature-1
分支状态。目前,提交 A
和 E
相同,因为在切换期间没有更改任何文件。
A ← master
\
E ← feature-1
现在,file1.txt
更新为新文本。使用此命令更新内容。
$ echo "file update in feature branch" > file1.txt
现在,file2.txt
具有以下内容。
$ cat file2.txt
This is dummy test in 2nd file
file1.txt
中新旧内容之间的差异可以使用以下命令进行验证。
$ git diff
diff --git a/file1.txt b/file1.txt
index 11d66d4..48c9378 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,2 +1 @@
-This is dummy text line 1
-This is dummy text line 2
+file update in feature branch
现在,暂存此文件并通过以下命令创建本地提交。
$ git add file1.txt
$ git commit -am "update file via feature-1"
[feature-1 22b60b8] update file via feature-1
1 file changed, 1 insertion(+), 2 d
提交树的当前快照如下所示。这里 F
是在上一步中创建的新提交。
A ← master
\
E --- F ← feature-1
为了演示一个真实的例子,远程 master
也被其他开发人员同时更改,这些更改作为提交 C
和提交 D
推送到 master。
A --- B --- C --- D ← master
\
E --- F ← feature-1
以下是 master 分支的 Github 仓库中 file1.txt
的更新内容。请注意,第 2 行已更新,第 3 行和第 4 行是新创建的。
这也可以通过使用以下命令在命令 shell 中实时可视化你的分支历史记录来本地验证。
$ git fetch
$ git log --all --decorate --oneline --graph
在 Git 中准备合并
使用 Git,我们有两种可能性将我们的功能分支更改与远程 master
分支合并:
-
merge
方法
Gitmerge
是一个将更改提交到另一个分支的命令。它允许开发人员从功能分支中获取他们独立的代码行,并通过 git 合并工具将它们集成到 master 上的单个分支中。 -
rebase
方法
Gitrebase
是另一个用于基本相同目的的命令,只是它的执行方式非常不同。
让我们详细了解这两种方式:
使用 Git 中的 merge
方法将分支合并到 Master 中
merge
旨在将 feature
和 master
分支合并到保留所有相关分支内容的提交中。Git 实现了这一点,即所谓的合并提交
。这也意味着 merge
操作多个分支。
当分支分叉时,即一个不是另一个的祖先。Git 可以通过进行具有多个父项的新附加提交来实现合并。在下图中,如果你在不同的分支中有提交 D
和提交 F
并混合分支(通过 git merge
),结果是提交 G
,其父项是 B
和 E
。
A --- B --- C --- D ---
\ \
\ G ← master
E --- F --------- /
在上图中,G
是一个新创建的提交,完全由 git 创建。这个提交有两个父节点!他们有一个命令:
- 第一个父节点是
D
,之前是master
。 - 第二个父节点是
F
,之前是feature-1
。
这种类型的提交称为合并提交。
现在切换回我们的仓库示例并将新创建的 feature-1
分支合并到 master
首先,检查主分支。
$ git checkout master
现在,将远程 master
更改拉到本地的 master
。
$ git pull origin master
From github.com:repo/demorepo
* branch master -> FETCH_HEAD
Updating 17cc6b4..a802b6b
Fast-forward
file1.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
之后,使用以下命令将功能分支,即 feature-1
合并到当前活动的分支。
$ git merge feature-1
如果此步骤成功完成,feature-1
分支将与 master
分支完全合并。但是,如果 git 不能自动解决这些合并冲突,它将失败并显示合并冲突错误。
这是一个非常典型的场景;当两个分支修改文件的同一部分并且 git 无法解析要使用的部分时,就会发生这种情况。这正是我们示例中发生的情况。下面通过 git 显示了这种情况。
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.
每当 git 遇到冲突时,它都会添加 <<<<<<<
& ========
以突出显示导致冲突的部分,这需要手动解决。
一旦决定将哪个部分保留在文件的最终主版本中,个人必须删除不相关的代码(包括冲突指示符)。最后,将更改推送到远程分支,如下所示。
$ git add .
$ git commit -am "resolving the mergeconflict"
[master 1acce69] resolving the mergeconflict
$ git push
这样 feature-1
分支成功合并到远程 master
。
接下来,我们将使用以下命令再次验证分支历史记录。
git log --all --decorate --oneline --graph
我们可以验证 git merge
是否创建了一个 Merge Commit
,commit-id 为 1acce69
以将 feature-1
分支与 origin/master
合并。
使用 rebase
方法将分支合并到 Master
再次考虑我们的 feature 和 master 分支不同步需要合并的情况。让我们还回顾一下之前显示这种情况的图示。
A --- B --- C --- D ← master
\
E --- F ← feature-1
作为合并的替代方法,你可以使用 rebase 选项将分支 feature-1
合并到分支 master
。rebase
通过简单地将来自 feature 分支的提交放在 master 分支的前面来统一所涉及的分支。
这将通过以下命令实现,
git checkout master
git pull
git checkout feature-1
git rebase master
运行 rebase 后,我们可以得到如下图所示。
A --- B --- C --- D----(operation rebase)----- E--------F ← master
从上图可以看出,rebase
所做的一些好事是产生线性、更清晰、更易于阅读的提交历史。通过合并,它也不会产生额外的奇怪的 merge commit
。
这种方法的缺点是 rebase 改变了所涉及分支的整个结构,包括重写这些分支的提交历史。由于 rebase
不会创建 merge commit
,你无法获得两个分支何时合并的可追溯性,因为 rebase 在流程结束时生成一个线性分支。
结论
这两个命令都非常有用;但是,在不同的情况下,双方各有优势。
Git rebase
- 简化复杂的历史。
- 避免在具有繁忙分支的仓库中合并提交噪音。
- 如果使用不当,则有风险,因为它不会保存历史。
Git merge
- 使用简单。
- 由于每次都会创建一个额外的合并提交,它会导致提交历史看起来混乱和肮脏。
- 保留完整的历史和时间顺序。