41.4.2 提交替换

    提交替换是在1.6.5或更新版本的Git中提供的功能,和提交嫁接类似,不过提交替换不是用一个提交来伪装成另外一个提交的父提交,而是直接替换另外的提交,在不影响其他提交的基础上实现对历史提交的修改。

    提交替换是通过在特殊命名空间.git/refs/replace/下定义引用来实现的。引用的名称是要被替换掉的提交SHA1哈希值,而引用文件的内容(引用所指向的提交)就是用于替换的(正确的)提交SHA1哈希值。由于提交替换通过引用进行定义,因此可以在不同的版本库之间传递,而不像提交嫁接只能在本地版本库中使用。

    Git提供git replace命令来管理提交替换,用法如下:


    用法1:git replace[-f]<object><replacement> 用法2:git replace-d<object>… 用法3:git replace-l[<pattern>]

    其中:

    用法1用于创建提交替换,即在.git/refs/replace目录下创建名为<object>的引用,其内容为<replacement>。如果使用-f参数,还允许级联替换,即用于替换的提交可以是另外一个已经在.git/refs/replace中定义的替换。

    用法2用于删除已经定义的替换。

    用法3显示已经存在的提交替换。

    提交替换可以被大部分Git命令理解,除了一些针对被替换的提交使用—no-replace-objects参数的命令。例如:

    当提交foo被提交bar替换后,显示未被替换前的foo提交:


    $git—no-replace-objects cat-file commit foo …foo的内容…

    不使用—no-replace-objects参数,则访问foo会显示替换后的bar提交:


    $git cat-file commit foo …bar的内容…

    提交替换使用引用进行定义,因此可以通过git fetch和git push在版本库之间传递。但因为默认Git只同步里程碑和分支,因此需要在命令中显式地给出提交替换的引用表达式,如:


    $git fetch origin refs/replace/* $git push origin refs/replace/*

    提交替换也可以实现两个分支的嫁接。例如要将分支A嫁接到B上,就相当于将分支A的根提交<BRANCH_A_ROOT>的父提交设置为分支B的最新提交<BRANCH_B_CURRENT>。可以先创建一个新提交<BRANCH_A_NEW_ROOT>,其父提交设置为<BRANCH_B_CURRENT>而提交的其他字段和<BRANCH_A_ROOT>完全一致。然后设置提交替换,用<BRANCH_A_NEW_ROOT>替换<BRANCH_A_ROOT>即可。

    可以使用下面的命令创建<BRANCH_A_NEW_ROOT>,注意要用实际值替换下面命令中的<BRANCH_A_ROOT>和<BRANCH_B_CURRENT>。


    $git cat-file commit<BRANCH_A_ROOT>| sed-e "/^tree/a\

    空标题文档 - 图1