Git 合并

来源:互联网 发布:xps和eds的区别 知乎 编辑:程序博客网 时间:2024/06/07 19:20

一、合并
为了把 other_branch 合并到 branch 中,你应该检出目标分支并把其他分支合并进去,如下所示:

$ git checkout branch$ git merge other_branch

二、为合并做准备
在开始合并之前,最好整理一下工作目录。在正常合并结束的时候,Git 会创建新版本的文件并把它放到工作目录中。此外,Git 在操作的时候还用索引来存储文件的中间版本。
如果已经修改了工作目录中的文件,或者已经通过 git add 或者 git rm 修改了索引,那么版本库里就已经有了一个脏的工作目录或者索引。如果在脏的状态下开始合并,Git 可能无法一次和并所有分支以及工作目录或索引的修改。
不必从干净的目录启动合并。例如,当受合并操作影响的文件和工作目录的脏文件无关的时候,Git 才进行合并。然而,作为一般规则,如果每次合并都从干净的工作目录和索引开始,那么关于 Git 的操作将会容易得多。

三、处理合并冲突
一个分支上的修改可能与一个不同的分支上的相似或完全不同。修改可能会改变相同的或无关的文件。Git 可以处理所有这些不同的可能性,但是通常需要你的指导来解决冲突。

定位冲突文件:
使用 git status 命令或者 git ls-files -u 命令来显示工作树中任然未合并的一组文件。

$ git statusOn branch masterYou have unmerged paths.  (fix conflicts and run "git commit")  (use "git merge --abort" to abort the merge)Unmerged paths:  (use "git add <file>..." to mark resolution)        both modified:   name.txtno changes added to commit (use "git add" and/or "git commit -a")$ git ls-files -u100644 e58835da4f1858ae5e279334b5dc747340635408 1       name.txt100644 7dab57c084e10c2125de87e512b81fb1305c3801 2       name.txt100644 27606668f6313d817d211efc570c4853a704c84a 3       name.txt

可以使用 git diff 命令来显示没合并的内容,但是它也会显示所有的细节。

检查冲突
当冲突出现时,通过三方比较或合并标记强调工作目录中的每个冲突文件的副本。

$ cat name.txtfoowt<<<<<<< HEADaj=======dj>>>>>>> new-branch

合并标记划定文件冲突部分的两个可能版本。可以简单地选择其中一个,移除冲突标记,然后执行 git add 和 git commit 命令。
三方合并标记线(<<<<<<<、=======、>>>>>>>)是自动生成的,它们只是给提供给你看的,一旦解决了冲突,就应该在文本编译器里删除他们。

对冲突使用 git diff 命令:
Git 有一个特殊的。特定于合并的 git diff 辩题来同时显示针对两个父版本做的修改

$ git diffdiff --cc name.txtindex 7dab57c,2760666..0000000--- a/name.txt+++ b/name.txt@@@ -1,8 -1,8 +1,9 @@@  foo  ang  msh  wt++<<<<<<< HEAD +aj++=======+ dj++>>>>>>> new-branch

这只是两个 diff 文件的简单组合:一个对应第一个称为 HEAD 的父版本,另一个对应第二个称为 new-branch 的父版本。Git 也给第二个父版本起了一个特殊的名字——MERGE_HEAD。

可以拿 HEAD 和 MERGE_HEAD 版本跟工作目录(“合并的”)版本进行比较。

在较新版本的 Git 中,git-diff –ours 是 git diff HEAD 的同义词,因为它显示了“我们的”版本和合并后版本的区别。同样,git diff MERGE_HEAD 可以写成 git diff –theirs。可以用 git diff –base 命令来查看自合并基础之后的变更组合。

对冲突使用 git log 命令:
在解决冲突的过程中,可以使用一些特殊的 git log 选项来帮助你找出变更的确切来源和原因。

$ git log --merge --left-right -pcommit < 245370451d194bbff90a7bd6236a37b129831211Author: Jon Loeliger <jdl@example.com>Date:   Tue Aug 8 10:30:59 2017 +0800    add ajdiff --git a/name.txt b/name.txtindex e58835d..7dab57c 100644--- a/name.txt+++ b/name.txt@@ -5,3 +5,4 @@ ang msh wt+ajcommit > e0b4372b68ad435586d8d1015d665c15edb5a870Author: Jon Loeliger <jdl@example.com>Date:   Tue Aug 8 10:28:55 2017 +0800    add djdiff --git a/name.txt b/name.txtindex e58835d..2760666 100644--- a/name.txt+++ b/name.txt@@ -5,3 +5,4 @@ ang msh wt+dj

在合并中的两个分支都影响冲突的文件,此命令将显示这两部分历史中的所有提交,并显示每次提交引入的实际变更。

git log 的选项如下:

  • –merge:只显示跟产生冲突的文件相关的提交。
  • –left-tight:如果提交来自合并的“左”边则显示<(“我们的”版本,就是你开始的版本),如果提交来自合并的“右”边则显示>(“他们的”版本,就是你要合并到的版本)
  • –p:显示提交信息和每个提交相关联的补丁。

如果版本库更加复杂而且有好几个文件发生冲突,也可以在命令行参数里指定确切的文件名:

$ git log --merge --left-right -p hello

小规模的提交和更频繁的合并周期可以减少解决冲突的痛苦。

结束解决冲突
在宣布合并前对冲突文件做最后一次修改。

$ cat name.txtfooangmshwtajdj

该文件已经完全合并而且解决冲突了,git add 命令就把索引再次简化为只有一份 name.txt 文件的副本。

$ git add name.txt$ git ls-files -s100644 088e2309c5b9be087c7a93c3da99c040714fa4a2 0       name.txt

git ls-files 的 -s 参数显示所有文件的各个阶段。
在 SHA1 和路径名中间单独的 0 表示无冲突文件的暂存编号是零。
必须解决索引中记录的所有冲突文件。只要有未解决的冲突就不能提交。因此,当解决一个文件的冲突之后,执行 git add(或者 git rm、git update-index等)以清除它的冲突状态。

注意:不要对有冲突标记的文件执行 git add 命令。虽然这会清除索引中的冲突,并允许提交,但文件将是错误的。

最后,对最终结果执行 git commit 命令。

中止或重新启动合并
在合并提交执行最后的 git commit 命令前,使用如下命令:

$ git reset --hard HEAD

这条命令立即把工作目录和索引都还原到 git merge 命令之前。

如果要中止或在它已经结束(也就是,引进一个新的合并提交)后放弃,请使用以下命令:

$ git reset --hard ORIG_HEAD

在开始合并操作前,GIt 把原分支的 HEAD 保存在 ORIG_HEAD .这是为了这种目的。