Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
- 2.47.1 11/25/24
- 2.46.1 → 2.47.0 no changes
- 2.46.0 07/29/24
- 2.45.1 → 2.45.2 no changes
- 2.45.0 04/29/24
- 2.43.1 → 2.44.2 no changes
- 2.43.0 11/20/23
- 2.41.1 → 2.42.3 no changes
- 2.41.0 06/01/23
- 2.40.1 → 2.40.3 no changes
- 2.40.0 03/12/23
- 2.39.1 → 2.39.5 no changes
- 2.39.0 12/12/22
- 2.38.1 → 2.38.5 no changes
- 2.38.0 10/02/22
- 2.1.4 → 2.37.7 no changes
- 2.0.5 12/17/14
概述
git merge-tree [--write-tree] [<选项>] <分支 1> <分支 2> git merge-tree [--trivial-merge] <基础目录树> <分支 1> <分支 2> (deprecated)
描述
该命令有现代的 --wirte-tree
模式和过时的 --trivial-merge
模式。 除了最后的 弃用说明 部分,本文档的其余部分描述的是现代的 --write-tree
模式。
执行合并,但不做任何新的提交,也不从工作区或索引中读取或写入。
执行的合并将使用与 “真正的” git-merge[1]相同的功能,包括:
-
单个文件的多路合并
-
rename detection
-
正确处理目录/文件冲突
-
递归祖先合并(即当有一个以上的合并基数时,通过合并基础创建一个虚拟合并基础)
-
等等。
合并完成后,会创建一个新的顶层树对象。 详见下面的 “输出”。
选项
- -z
-
在 <冲突文件信息> 部分不要引用文件名,每个文件名用 NUL 字符而不是换行来结束。 在信息部分也要用 NUL 字符而不是换行来开始。 更多信息见下面的 输出。
- --name-only
-
在冲突的文件信息部分,不要为冲突的文件写一个(mode, oid, stage, path)图元列表来输出,只需提供一个有冲突的文件名列表(如果文件有多个冲突的阶段,不多次列出文件名)。
- --[no-]messages
-
将任何信息性的消息,如"Auto-merging <path>" 或冲突通知写到标准输出流的末尾。 如果没有指定,默认情况下,如果有合并冲突,就包括这些信息,否则就省略它们。
-
如果指定的两个分支没有共同的历史,merge-tree 默认会出错。 这个标志可以用来覆盖这个检查,并使合并继续进行。
- --merge-base=<tree-ish>
-
不需要为 <branch1> 和 <branch2> 寻找合并基础,而是为合并指定一个合并基础,目前不支持指定多个合并基础。该选项与
--stdin
不兼容。由于直接提供了合并基础,<分支 1> 和 <分支 2> 不需要指定提交;树对象就足够了。
- -X<选项>
- --strategy-option=<选项>
-
将合并策略特有的选项传递给合并策略。 详见 git-merge[1]。
输出
对于一个成功的合并,git-merge-tree 的输出仅仅是一行:
<OID of toplevel tree>
而对于有冲突的合并,默认的输出形式是:
<OID of toplevel tree> <Conflicted file info> <Informational messages>
下面将分别讨论这些问题。
然而,有一个例外。 如果通过了 --stdin
,那么在开头有一个额外的部分,在结尾有一个 NUL 字符,然后所有的部分在每行输入中都会重复。 因此,如果第一次合并是冲突的,而第二次是干净的,输出将是这样的形式:
<Merge status> <OID of toplevel tree> <Conflicted file info> <Informational messages> NUL <Merge status> <OID of toplevel tree> NUL
Merge status
这是一个整数状态,后面有一个 NUL 字符。 整数状态是:
0:合并后有冲突 1: 合并是干净的 <0:有什么东西阻止了合并的运行(例如,文件系统拒绝对仓库对象的访问 对象的访问被文件系统拒绝)
顶层目录树的 OID
这是一个树状对象,代表在`git merge` 结束时工作区上检查出来的东西。 如果有冲突,那么这个目录树中的文件可能会有嵌入式冲突标记。 这一部分的后面总是有一个换行符(如果传递了 -z
则为 NUL)。
冲突的文件信息
这是一连串的行,格式为
<mode> <object> <stage> <filename>
文件名将按照配置变量 core.quotePath
的说明加引号(参见 git-config[1])。 不过,如果通过了 --name-only`选项,则会省略模式、对象和阶段。 如果传递了 `-z
选项,“行” 将以 NUL 字符而不是换行符结束。
信息
这一部分提供信息,通常是关于冲突的信息。 该部分的格式因是否传递了 -z
而有很大不同。
如果 `-z`被传递:
输出格式是零条或更多的冲突信息记录,每条记录的形式都是:
<list-of-paths><conflict-type>NUL<conflict-message>NUL
其中 <list-of-paths> 的形式为
<number-of-paths>NUL<path1>NUL<path2>NUL...<pathN>NUL
并包括受冲突影响的路径(或分支名称)或 <conflict-message> 中的信息消息。 另外,<conflict-type> 是一个稳定的字符串,解释了冲突的类型,比如说
-
"Auto-merging"
-
"CONFLICT (重命名/删除)"
-
"CONFLICT (子模块缺乏合并基础)"
-
"CONFLICT (二进制)"
和 <conflict-message> 是关于冲突的更详细的信息,通常(但不一定)会嵌入 <stable-short-type-description> 中。 这些字符串在未来的Git版本中可能会改变。 一些例子:
-
"Auto-merging <文件>"
-
"CONFLICT (rename/delete): <oldfile> 被重命名… 但在… 被删除。"
-
“合并子模块 <submodule> 失败(没有合并基础)”
-
“警告:不能合并二进制文件: <filename>”
如果没有传递 -z
:
这一节以空行开始,与前几节分开,然后只包含前一节的 <conflict-message> 信息(用换行符分开)。 这些是不稳定的字符串,不应该被脚本解析,只是为了供人使用。 另外,请注意,虽然 <conflict-message> 字符串通常不包含嵌入式换行符,但有时也会包含。 (然而,自由格式的信息永远不会有一个嵌入的 NUL 字符)。 所以,整个信息块是作为所有冲突信息的集合体提供给人类阅读的。
退出状态码
如果合并成功,没有冲突,退出状态为 0;如果合并有冲突,退出状态为 1;如果合并由于某种错误而无法完成(或开始),退出状态为 0 或 1 以外的内容(而且输出结果未指明)。 当传递 --stdin 时,对于成功的合并和有冲突的合并,返回状态都是 0,如果不能完成所有要求的合并,则返回 0 或 1 以外的其他状态。
使用说明
这个命令旨在作为低级的底层命令,类似于 git-hash-object[1],git-mktree[1], git-commit-tree[1], git-write-tree[1],git-update-ref[1] 和 git-mktag[1]。 因此,它可以作为一系列步骤的一部分来使用,比如:
NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) test $? -eq 0 || die "There were conflicts..." NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2) git update-ref $BRANCH1 $NEWCOMMIT
注意,当退出状态为非零时,这个序列中的 NEWTREE
将包含很多输出,而不仅仅是一棵目录树。
对于冲突,输出包括你用 git-merge[1] 得到的相同信息:
-
什么会被写入工作区(顶层目录树树的 OID)
-
将被写入索引的高阶阶段(冲突的文件信息)
-
任何会被打印到标准输出流的信息(信息性信息)
输入格式
git merge-tree --stdin 的输入格式是完全基于文本的。每一行都有这样的格式:
[<基础提交> -- ]<分支1> <分支2>
如果一行被 --
分隔,分隔符前的字符串用于指定合并的基础,分隔符后的字符串描述要合并的分支。
应避免的错误
不要在产生的顶层目录树中寻找哪些文件有冲突,而要解析 冲突文件信息 部分。 在大型存储库中,不仅解析整个目录树会慢得吓人,而且有许多冲突类型无法用冲突标记来表示(修改/删除,模式冲突,二进制文件在两边都有改变,文件/目录冲突,各种重命名冲突的变种,等等。)
不要把一个空的 冲突文件信息 列表理解为一个干净的合并;检查退出状态。 一个合并可以有冲突而没有单个文件的冲突(有几种类型的目录重命名冲突属于这个类别,其他的也可能在将来被添加)。
不要试图猜测或让用户猜测 冲突文件信息 列表中的冲突类型。 那里的信息不足以做到这一点。 比如说: Rname/rename( 1 对 2 )冲突(双方以不同方式重命名同一文件)将导致三个不同的文件具有高阶阶段(但每个文件只有一个高阶阶段),没有办法(除了 信息消息 部分)确定哪三个文件是相关的。 文件/目录冲突也会导致一个文件正好有一个高阶阶段。 可能涉及目录重命名的冲突(当 "merge.directoryRenames" 未设置或设置为 "conflict" 时)也会导致一个文件正好有一个高阶阶段。 在所有情况下,消息性信息 部分都有必要的信息,尽管它不是被设计为可被机器解析的。
不要假设 冲突文件信息 中的每个路径和 信息消息 中的逻辑冲突有一对一的映射,也不要假设存在一对多的映射,更不要假设存在多对一的映射。 存在多对多的映射,意味着每个路径在一次合并中可以有许多逻辑冲突类型,每个逻辑冲突类型可以影响许多路径。
不要认为 信息消息 部分列出的所有文件名都有冲突。 对于没有冲突的文件,可以包括信息,如 "Auto-merging <文件>"。
弃用说明
根据 DESCRIPTION,与本文档的其他部分不同,本节描述了被废弃的 --trivial-merge
模式。
除了可选的 --trivial-merge
外,该模式不接受任何选项。
这种模式读取三个树状的,并将琐碎的合并结果和冲突的阶段以 semi-diff 格式输出到标准输出。 由于这是为更高级别的脚本设计的,以消耗并将结果合并回索引中,所以它省略了与 <branch1> 相匹配的条目。 第二种形式的结果类似于三方 "git read-tree -m" 的做法,但该命令不是将结果存储在索引中,而是将条目输出到标准输出。
这种形式不仅适用性有限(一个琐碎的合并不能处理单个文件的内容合并、重命名检测、适当的目录/文件冲突处理等),输出格式也很难处理,而且即使在成功的合并中,它的性能一般也不如第一种形式(特别是在大型仓库中工作)。
GIT
属于 git[1] 文档