Git 分支 - 基本分支和合并
- 基本分支和合并
- 基本分支
- 基本合并
- 基本合并冲突
基本分支和合并
让我们通过一个简单的示例,将分支和合并与您可能在现实世界中使用的工作流合并。您将按照以下步骤操作:
在网站上做一些工作。
为您正在处理的新用户情景创建分支。
在该分支中执行一些工作。
在此阶段,您将收到一个电话,指出另一个问题很严重,您需要一个修补程序。您将执行以下操作:
切换到生产分支。
创建分支以添加此修补程序。
测试后,合并修补程序分支,然后推送到生产环境。
切换回原始用户情景并继续工作。
基本分支
首先,假设您正在处理您的项目,并且已经在分支上进行了几次提交。master
您已经决定要在公司使用的任何问题跟踪系统中处理问题#53。要创建新分支并同时切换到该分支,可以使用 switch 运行以下命令:git checkout-b
$ git checkout -b iss53
Switched to a new branch "iss53"
这是以下各项的简写:
$ git branch iss53
$ git
你在你的网站上工作并做一些提交。这样做会将分支向前移动,因为您已将其签出(即,您正在指向它):iss53HEAD
$ vim index.html
$ git commit -a -m 'Create new footer [issue 53]'
现在,您接到电话,指出该网站存在问题,您需要立即修复它。使用 Git,您不必将修复程序与所做的更改一起部署,也不必花费大量精力来还原这些更改,然后才能将修补程序应用于生产环境中的内容。您所要做的就是切换回您的分支机构。iss53master
但是,在执行此操作之前,请注意,如果您的工作目录或暂存区域具有与要签出的分支冲突的未提交更改,Git 将不允许您切换分支。切换分支时最好有一个干净的工作状态。有一些方法可以解决这个问题(即,隐藏和提交修改),我们将在稍后的存储和清理中介绍。现在,假设您已经提交了所有更改,因此您可以切换回分支:master
$ git checkout master
Switched to branch 'master'
此时,您的项目工作目录与您开始处理问题 #53 之前完全相同,您可以专注于您的修补程序。这是需要记住的重要一点:当您切换分支时,Git 会重置您的工作目录,使其看起来像您上次在该分支上提交时的样子。它会自动添加、删除和修改文件,以确保您的工作副本是上次提交时分支的样子。
接下来,您将有一个要制作的修补程序。让我们创建一个分支,直到完成为止:hotfix
$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'Fix broken email address'
[hotfix 1fb7853] Fix broken email address
1 file changed, 2 insertions(+)
您可以运行测试,确保修补程序是所需的,最后将分支合并回分支以部署到生产环境。您可以使用以下命令执行此操作:hotfixmastergit merge
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
您会注意到该合并中的短语“快进”。由于您合并的分支所指向的提交正好在您所在的提交之前,因此 Git 只需将指针向前移动即可。换句话说,当你尝试将一个提交与可以通过跟踪第一个提交的历史记录来达到的提交合并时,Git通过向前移动指针来简化事情,因为没有不同的工作可以合并在一起 - 这被称为“快进”。C4hotfixC2
您的更改现在位于分支所指向的提交的快照中,您可以部署修复程序。master
部署超级重要的修复程序后,您就可以切换回在中断之前所做的工作。但是,首先要删除分支,因为您不再需要它 - 分支指向同一位置。您可以通过以下选项将其删除:hotfixmaster-dgit branch
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
现在,您可以切换回问题 #53 上的“在制品”分支,并继续处理它。
$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'Finish the new footer [issue 53]'
[iss53 ad82d7a] Finish the new footer [issue 53]
1 file changed, 1 insertion(+)
这里值得注意的是,您在分支中所做的工作不包含在分支中的文件中。如果需要将其拉入,可以通过运行 将分支合并到分支中,也可以等待集成这些更改,直到您决定稍后将分支拉回。hotfixiss53masteriss53git merge masteriss53master
基本合并
假设您已经确定您的问题 #53 工作已完成,并准备合并到您的分支中。为此,您需要将分支合并到 中,就像您之前合并分支一样。您所要做的就是签出要合并到的分支,然后运行以下命令:masteriss53masterhotfixgit merge
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
这看起来与您之前所做的合并略有不同。在这种情况下,您的开发历史已经偏离了某个较旧的点。因为你所在的分支上的提交不是你要合并的分支的直接祖先,所以 Git 必须做一些工作。在这种情况下,Git 使用分支提示所指向的两个快照和两者的共同祖先执行简单的三向合并。hotfix
Git 不会只是将分支指针向前移动,而是创建一个由此三向合并产生的新快照,并自动创建指向它的新提交。这称为合并提交,其特殊之处在于它具有多个父级。
现在您的工作已合并,您不再需要该分支。您可以在问题跟踪系统中关闭问题,然后删除分支:iss53
$ git branch -d iss53
基本合并冲突
有时,此过程不会顺利进行。如果您在要合并的两个分支中以不同的方式更改了同一文件的同一部分,Git 将无法干净地合并它们。如果问题 #53 的修复修改了与分支相同的文件部分,则会出现如下所示的合并冲突:hotfix
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then
Git 尚未自动创建新的合并提交。它已暂停该过程,而您解决冲突。如果要查看合并冲突后任何时候哪些文件未合并,可以运行:git status
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." 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.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>>
这意味着(您的分支,因为这是您在运行合并命令时签出的版本)是该块的顶部(上面的所有内容),而分支中的版本看起来像底部的所有内容。为了解决冲突,您必须选择一方或另一方或自己合并内容。例如,您可以通过将整个块替换为以下内容来解决此冲突:HEADmaster=======iss53
<div id="footer">
please contact us at xq.com
</div>
此分辨率的每个部分都有一点,并且 、 和行已被完全删除。在每个冲突的文件中解决其中每个部分后,对每个文件运行以将其标记为已解决。暂存文件在 Git 中将其标记为已解决。<<<<<<<=======>>>>>>>git add
如果要使用图形工具来解决这些问题,可以运行 ,这将启动相应的可视合并工具并引导您完成冲突:git mergetool
$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html
Normal merge conflict for 'index.html':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (opendiff):
如果要使用默认工具以外的合并工具(Git 在本例中选择,因为该命令是在 Mac 上运行的),则可以在顶部“以下工具之一”之后看到所有受支持的工具。只需键入您更愿意使用的工具的名称即可。opendiff
退出合并工具后,Git 会询问合并是否成功。如果您告诉脚本它是,它会暂存该文件以将其标记为已为您解析。您可以再次运行以验证是否已解决所有冲突:git status
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
如果您对此感到满意,并且验证所有发生冲突的内容都已暂存,则可以键入以完成合并提交。默认情况下,提交消息如下所示:git commit
Merge branch 'iss53'
Conflicts:
index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: index.html
#
如果您认为这对将来查看此合并的其他人有帮助,则可以修改此提交消息,其中包含有关如何解决合并的详细信息,并解释为什么在更改不明显时进行更改。