可能会遇到的工作流
开发某个网站
为实现某个新的用户需求,创建一个分支
在这个分支上开展新工作
正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补,你将按照如下方式来处理:
切换到你的线上分支(production branch)
为这个紧急任务新建一个分支,并在其中修复它
在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分支
切换回你最初工作的分支上,继续工作
首先,我们假设你正在你的项目上工作,并且在 master
分支上已经有了一些提交。
为了解决问题,想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 -b
参数的 git checkout
命令
$ git checkout -b iss53 Switched to a new branch "iss53"
它是下面两条命令的简写
$ git branch iss53 $ git checkout iss53
在 iss53
分支上修改东西并提交,该分支就会不断的向前推进,因为已经 checkout 到该分支 (也就是说,HEAD
指针指向了 iss53
分支)
$ vim index.html $ git commit -a -m 'added a new footer [issue 53]'
突然紧急插入一个问题需要修复,它可以不用和 iss53 分支混在一起,操作步骤
$ git checkout master Switched to branch 'master'
这个时候,Git 会让工作目录的内容会和 master 分支上最后一次提交时的内容保持一致,它会自动添加、删除、修改工作目录的文件
为了修复问题,新建一个分支在上面工作直到问题修复成功
$ git checkout -b hotfix Switched to a new branch 'hotfix' $ vim index.html $ git commit -a -m 'fixed the broken email address' [hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+)
问题修复成功后,可以将 hotfix
分支合并回 master
分支来部署到线上
$ git checkout master $ git merge hotfix Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+)
hotfix
所指向的提交 C4
是你所在的提交 C2
的直接后继, 因此 Git 会直接将指针向前移动现在,最新的修改已经在 master
分支所指向的提交快照中,可以提交发布修复了
问题解决后,删除临时分支,因为不再需要它,而且 master 分支也指向同一个位置了
$ git branch -d hotfix Deleted branch hotfix (3a0874c).
回到 iss53 分支继续工作,继续提交
$ 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(+)
hotfix
分支上所做的工作并没有包含到 iss53
分支hotfix
所做的修改,可以使用 git merge master
命令将 master
分支合并入 iss53
分支,或者也可以等到 iss53
分支完成其使命,再将其合并回 master
分支
iss53 分支上工作已完成,回到 master 分支合并 iss53 的东西
$ git checkout master Switched to branch 'master' $ git merge iss53 Merge made by the 'recursive' strategy. index.html | 1 + 1 file changed, 1 insertion(+)
master
分支所在提交并不是 iss53
分支所在提交的直接祖先,Git 不得不做一些额外的工作C4
和 C5
)以及这两个分支的公共祖先(C2
),做一个简单的三方合并和之前将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它,它的特别之处在于他有不止一个父提交
既然修改已经合并进来了,就不再需要 iss53
分支了
$ git branch -d iss53
hotfix
分支的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突$ 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 status
命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件$ 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> >>>>>>> iss53:index.html
HEAD
所指示的版本<<<<<<< HEAD:index.html <div id="footer">contact : email.support@github.com</div>
这也是 master 分支下的文件内容,也是冲突的部分内容
<div id="footer"> please contact us at support@github.com </div> >>>>>>> iss53:index.html
这是 iss53 分支下的文件内容,和 master 分支的内容冲突了,此时你必须二选一保留一个
<div id="footer"> please contact us at email.support@github.com </div>
<<<<<<<
, =======
, 和 >>>>>>>
这些行需要删除哦
在解决了所有文件里的冲突之后,对每个文件使用 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 status On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: index.html
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 #