- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅析Git 分支的新建与合并由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
分支的新建与合并 。
现在让我们来看一个简单的分支与合并的例子,实际工作中大体也会用到这样的工作流程:
假设此时,你突然接到一个电话说有个很严重的问题需要紧急修补,那么可以按照下面的方式处理:
分支的新建与切换 。
首先,我们假设你正在项目中愉快地工作,并且已经提交了几次更新(见图 3-10).
图 3-10. 一个简短的提交历史 。
现在,你决定要修补问题追踪系统上的 #53 问题。顺带说明下,git 并不同任何特定的问题追踪系统打交道。这里为了说明要解决的问题,才把新建的分支取名为 iss53。要新建并切换到该分支,运行git checkout并加上-b参数:
1
2
|
$ git checkout -b iss53
switched to a new branch
'iss53'
|
这相当于执行下面这两条命令:
1
2
|
$ git branch iss53
$ git checkout iss53
|
图 3-11 示意该命令的执行结果.
图 3-11. 创建了一个新分支的指针 。
接着你开始尝试修复问题,在提交了若干次更新后,iss53分支的指针也会随着向前推进,因为它就是当前分支(换句话说,当前的head指针正指向iss53,见图 3-12):
1
2
|
$ vim index.html
$ git commit -a -m
'added a new footer [issue 53]'
|
图 3-12. iss53 分支随工作进展向前推进 。
现在你就接到了那个网站问题的紧急电话,需要马上修补。有了 git ,我们就不需要同时发布这个补丁和iss53里作出的修改,也不需要在创建和发布该补丁到服务器之前花费大力气来复原这些修改。唯一需要的仅仅是切换回master分支.
不过在此之前,留心你的暂存区或者工作目录里,那些还没有提交的修改,它会和你即将检出的分支产生冲突从而阻止 git 为你切换分支。切换分支的时候最好保持一个清洁的工作区域。稍后会介绍几个绕过这种问题的办法(分别叫做 stashing 和 commit amending)。目前已经提交了所有的修改,所以接下来可以正常转换到master分支:
1
2
|
$ git checkout master
switched to branch
'master'
|
此时工作目录中的内容和你在解决问题 #53 之前一模一样,你可以集中精力进行紧急修补。这一点值得牢记:git 会把工作目录的内容恢复为检出某分支时它所指向的那个提交对象的快照。它会自动添加、删除和修改文件以确保目录的内容和你当时提交时完全一样.
接下来,你得进行紧急修补。我们创建一个紧急修补分支hotfix来开展工作,直到搞定(见图 3-13):
1
2
3
4
5
6
|
$ git checkout -b hotfix
switched to a new branch
'hotfix'
$ vim index.html
$ git commit -a -m
'fixed the broken email address'
[hotfix 3a0874c] fixed the broken email address
1 files changed, 1 deletion(-)
|
图 3-13. hotfix 分支是从 master 分支所在点分化出来的 。
有必要作些测试,确保修补是成功的,然后回到master分支并把它合并进来,然后发布到生产服务器。用git merge命令来进行合并:
1
2
3
4
5
6
|
$ git checkout master
$ git merge hotfix
updating f42c576..3a0874c
fast-forward
readme | 1 -
1
file
changed, 1 deletion(-)
|
请注意,合并时出现了“fast forward”的提示。由于当前master分支所在的提交对象是要并入的hotfix分支的直接上游,git 只需把master分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(fast forward).
现在最新的修改已经在当前master分支所指向的提交对象中了,可以部署到生产服务器上去了(见图 3-14).
图 3-14. 合并之后,master 分支和 hotfix 分支指向同一位置.
在那个超级重要的修补发布以后,你想要回到被打扰之前的工作。由于当前hotfix分支和master都指向相同的提交对象,所以hotfix已经完成了历史使命,可以删掉了。使用git branch的-d选项执行删除操作:
1
2
|
$ git branch -d hotfix
deleted branch hotfix (was 3a0874c).
|
现在回到之前未完成的 #53 问题修复分支上继续工作(图 3-15):
1
2
3
4
5
6
|
$ git checkout iss53
switched to branch
'iss53'
$ vim index.html
$ git commit -a -m
'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1
file
changed, 1 insertion(+)
|
图 3-15. iss53 分支可以不受影响继续推进.
值得注意的是之前hotfix分支的修改内容尚未包含到iss53中来。如果需要纳入此次修补,可以用git merge master把 master 分支合并到iss53;或者等iss53完成之后,再将iss53分支中的更新并入master.
删除远程分支
1
|
$ git push origin --delete <branchname>
|
查看远程分支
1
|
$ git branch -a
|
分支的合并 。
在问题 #53 相关的工作完成之后,可以合并回master分支。实际操作同前面合并hotfix分支差不多,只需回到master分支,运行git merge命令指定要合并进来的分支:
1
2
3
4
5
6
|
$ git checkout master
$ git merge iss53
auto-merging readme
merge made by the
'recursive'
strategy.
readme | 1 +
1
file
changed, 1 insertion(+)
|
请注意,这次合并操作的底层实现,并不同于之前hotfix的并入方式。因为这次你的开发历史是从更早的地方开始分叉的。由于当前master分支所指向的提交对象(c4)并不是iss53分支的直接祖先,git 不得不进行一些额外处理。就此例而言,git 会用两个分支的末端(c4 和 c5)以及它们的共同祖先(c2)进行一次简单的三方合并计算。图 3-16 用红框标出了 git 用于合并的三个提交对象:
图 3-16. git 为分支合并自动识别出最佳的同源合并点.
这次,git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(c6)(见图 3-17)。这个提交对象比较特殊,它有两个祖先(c4 和 c5).
值得一提的是 git 可以自己裁决哪个共同祖先才是最佳合并基础;这和 cvs 或 subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让 git 的合并操作比其他系统都要简单不少.
图 3-17. git 自动创建了一个包含了合并结果的提交对象.
既然之前的工作成果已经合并到master了,那么iss53也就没用了。你可以就此删除它,并在问题追踪系统里关闭该问题.
1
|
$ git branch -d iss53
|
遇到冲突时的分支合并 。
有时候合并操作并不会如此顺利。如果在不同的分支中都修改了同一个文件的同一部分,git 就无法干净地把两者合到一起(译注:逻辑上说,这种问题只能由人来裁决。)。如果你在解决问题 #53 的过程中修改了hotfix中修改的部分,将得到类似下面的结果:
1
2
3
4
|
$ git merge iss53
auto-merging index.html
conflict (content): merge conflict
in
index.html
automatic merge failed; fix conflicts and
then
commit the result.
|
git 作了合并,但没有提交,它会停下来等你解决冲突。要看看哪些文件在合并时发生冲突,可以用git status查阅:
1
2
3
4
5
6
7
8
9
10
11
|
$ 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"
)
|
任何包含未解决冲突的文件都会以未合并(unmerged)的状态列出。git 会在有冲突的文件里加入标准的冲突解决标记,可以通过它们来手工定位并解决这些冲突。可以看到此文件包含类似下面这样的部分:
1
2
3
4
5
6
7
|
<<<<<<<
head
<div
id
=
"footer"
>contact : email.support@github.com<
/div
>
=======
<div
id
=
"footer"
>
please contact us at support@github.com
<
/div
>
>>>>>>> iss53
|
可以看到=======隔开的上半部分,是head(即master分支,在运行merge命令时所切换到的分支)中的内容,下半部分是在iss53分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。比如你可以通过把这段内容替换为下面这样来解决:
1
2
3
|
<div
id
=
"footer"
>
please contact us at email.support@github.com
<
/div
>
|
这个解决方案各采纳了两个分支中的一部分内容,而且我还删除了<<<<<<<,=======和>>>>>>>这些行。在解决了所有文件里的所有冲突后,运行git add将把它们标记为已解决状态(译注:实际上就是来一次快照保存到暂存区域。)。因为一旦暂存,就表示冲突已经解决。如果你想用一个有图形界面的工具来解决这些问题,不妨运行git mergetool,它会调用一个可视化的合并工具并引导你解决所有冲突:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ 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 为我默认选择了opendiff,因为我在 mac 上运行了该命令),你可以在上方"merge tool candidates"里找到可用的合并工具列表,输入你想用的工具名。我们将在第七章讨论怎样改变环境中的默认值.
退出合并工具以后,git 会询问你合并是否成功。如果回答是,它会为你把相关文件暂存起来,以表明状态为已解决.
再运行一次git status来确认所有冲突都已解决:
1
2
3
4
5
6
|
$ git status
on branch master
changes to be committed:
(use
"git reset head <file>..."
to unstage)
modified: index.html
|
如果觉得满意了,并且确认所有冲突都已解决,也就是进入了暂存区,就可以用git commit来完成这次合并提交。提交的记录差不多是这样:
1
2
3
4
5
6
7
8
9
10
|
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.
#
|
如果想给将来看这次合并的人一些方便,可以修改该信息,提供更多合并细节。比如你都作了哪些改动,以及这么做的原因。有时候裁决冲突的理由并不直接或明显,有必要略加注解.
总结 。
到此这篇关于git 分支的新建与合并的文章就介绍到这了,更多相关git 分支内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/fnlingnzb-learner/p/10511235.html 。
最后此篇关于浅析Git 分支的新建与合并的文章就讲到这里了,如果你想了解更多关于浅析Git 分支的新建与合并的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我目前正在开发自己的内存泄漏跟踪系统。 我正在使用 Microsoft Visual C++ 2008,我知道他们有一个内置的,但我一直在为自己制作一个,只是为了好玩。 但是,当我覆盖 new 和 n
在我的库(替换全局 new/delete 运算符)中,我使用另一个外部库(casablanca pplx)。此外部库不包含替换的 new/delete 运算符(我使用 Visual Studio 的
最近的 C++ 标准中的内存分配操作是否有复杂性保证?也就是说,如果我有一个类 A,其默认构造函数和析构函数在 O(1) 中运行,那么“new A[N]”和“delete[] A”的 big-O 是什
我正在用 Qt 和 C++ 编写一个简单的编辑器。我想要有标签,所以在创建新文档后,我想在新标签中打开它。我的代码: // mainwindow.cpp #include "mainwindow.h"
好吧,这让我感到困惑...下面的代码在一个 DLL 中,当我的控制台应用程序调用这段代码时,它突然在 delete[] lpBuffer 行抛出访问冲突。我整天都在使用这段代码,根本没有改变它。到目前
我现在很头疼。 基本上我有这个: Class A -> Class B Class A -> Class C Class A -> Class D Class E with constructor w
我想通过将一个表 (tableA) 与另一个表 (tableB) 进行比较来查找新的、修改的和删除的记录。两个表具有相同的模式并具有唯一的 ID 字段。 在我的情况下,tableA 最初与 table
这是我们的商业案例, 应用程序为使用过的 iPhone 提供即时报价,并允许卖家立即出售。另一方面,有些买家愿意立即购买或竞标房源。潜在的零售商可以访问网站并根据年份、型号、状况、配件输入获得即时报价
需要一些帮助。设法创建一个 jQuery 来在单击后更改按钮的类,但我需要您单击一个从其他按钮中删除的新按钮类。 我正在努力,但我做不到。我已经尝试了一些方法,但每当我尝试时,我都可以删除所有内容并单
为什么“创建 Java 项目”屏幕中有时会缺少“内容”部分(带有“从现有源创建项目”选项)?我知道我以前见过并使用过它,但现在它已经消失了。 最佳答案 您最好在 Eclipse JDT 论坛上提出这个
我写了下面的代码 1. function Car() { this.make = "BMW" } var x = new Car().make alert(x) 结果:显示警报 BMW 2. fu
我正在使用 wxPython 为 python 应用程序编写 UI。我已经处理了一些 OnX 函数,但我需要 OnNew 和 OnSave/SaveAs 方面的帮助 这是我的保存和另存为代码: def
每当我尝试创建一个新的 Win32 控制台应用程序或 Win32 项目时,Win32 应用程序向导弹出,项目设置项目符号点为空,并且无法单击“应用程序设置”、“完成”和“取消”按钮. 当我搜索与我类似
我创建了一个扩展点 newWizard,并在那里添加了向导(比方说 Wizard1、Wizard2、Wizard3)。我创建了一个视角,即 perspectiv1。当我创建插件项目时,所有向导标签都会
新建 >> 项目 >> Android 应用程序 项目不起作用我收到这些消息: Problem Opening Wizard The selected wizard could not be star
#include #include using namespace std; int main(void) { unsigned char* pFoo = new unsigned cha
谁能帮我理解为什么我的代码在第一段代码中的 delete[] szPassword 上失败?我知道 szPassword 只是复制“a”,而 st2 等于 8: TCHAR *szPassword =
伙计们,如果我在我的 dll 代码中覆盖全局新建和删除,这会覆盖用户代码新建和删除吗?我做了一个测试,显示用户new和delete不会受到影响。如果我想让用户代码new和delete被我的sdk ne
编译 in_ 表达式的默认 SQLAlchemy 行为对于非常大的列表来说是病态的,我想为运算符创建一个自定义的、更快的编译器。如果解决方案是一个新的运算符(即:in_list_)或者它是否覆盖了 i
new 和 delete 被称为预处理器,而 malloc 和 free 是函数。 new 和 delete 是预处理器是什么意思? 最佳答案 new 和 delete 是 C++ 运算符(如 +、(
我是一名优秀的程序员,十分优秀!