跳转到主要内容

Git增量合并

项目描述

git-imerge -- Git的增量合并和变基工具

在两个分支之间进行增量合并。如果遇到冲突,确定确切的冲突提交对,并一次呈现一个提交对给用户进行解决。

git-imerge有两个主要设计目标

  • 通过找到并呈现最小的冲突(即每个分支引入的一个提交之间的变化)来将解决合并冲突的痛苦减少到不可避免的最小。

  • 允许在合并过程中保存、测试、中断、发布和协作。

我认为通过视觉方式理解增量合并的概念更容易,因此我推荐观看我在GitMerge 2013会议上的git-imerge演示视频(20分钟),这是一个很好的起点。该演讲的全部幻灯片可在本存储库中的doc/presentations/GitMerge-2013部分找到。在同一个会议上,我被Thomas Ferris Nicolaisen采访,讨论了git-imerge,该采访可在他的GitMinutes播客#12中找到。

要了解如何使用 git-imerge 工具本身,我建议阅读博客文章 git-imerge:实用入门,也可以通过输入 git-imerge --helpgit-imerge SUBCOMMAND --help 来获取更多信息。如果你想了解更多信息,增量合并的理论和好处可以在一系列博客文章中详细描述[1],同样还有在rebase时保留历史的好处[2]。

可以同时进行多个增量合并。每个增量合并都有一个名称,其进度会记录在Git仓库中,作为 refs/imerge/NAME 下的引用。可以使用 diagram 命令来可视化增量合并的当前状态。

增量合并可以被任意中断和恢复,甚至可以推送到服务器,让其他人继续工作。

git-imerge 包含一个Bash完成脚本 completions/git-imerge,在安装 git-imerge 时会自动安装。

要求

git-imerge 需要:

  • 一个Python解释器;可以是:

    • Python 3.x,版本 3.3 或更高。

    • Python 2.x,版本 2.6 或更高。如果你使用的是Python 2.6.x,那么你必须自己安装 argparse 模块,因为它是在Python 2.7中添加到标准库的。

  • Git的较新版本。

Bash完成需要Git的完成功能可用。

安装

git-imerge 在PyPI_上可用,因此你可以使用 pip 来安装它

$ pip install git-imerge

或者如果你已经下载了源代码包,可以使用 setup.py 进行安装

$ python setup.py install

说明

要使用 git-imerge 开始合并或rebase操作,你可以使用与相应 git 命令相似的命令

git-imerge 命令 git 类似命令 效果
git-imerge merge BRANCH git merge BRANCH BRANCH 合并到当前分支
git-imerge rebase BRANCH git rebase BRANCH 将当前分支基于 BRANCH 进行rebase
git-imerge revert COMMIT git revert COMMIT 添加一个新的提交,该提交取消 COMMIT 的影响
git-imerge revert COMMIT1..COMMIT2 git revert COMMIT1..COMMIT2 添加新的提交,取消 COMMIT1..COMMIT2 的影响
git-imerge drop COMMIT git rebase --onto COMMIT^ COMMIT 完全从当前分支的历史中删除提交 COMMIT
git-imerge drop COMMIT1..COMMIT2 git rebase --onto COMMIT1 COMMIT2 完全从当前分支的历史中删除提交 COMMIT1..COMMIT2

git-imerge drop 也类似于运行 git rebase --interactive,然后从历史中删除指定的提交。这两个子命令都被包含在git-imerge中,因为等效的git操作可能会冲突,所以它们都可以从增量合并方法中受益。)

如果你使用 git imerge start 开始增量合并,还有更多选项可用

$ git-imerge start --name=NAME --goal=GOAL [--first-parent] BRANCH

其中:

  • NAME 是这个合并的名称(也是结果将保存到的分支的默认名称)。

  • GOAL 描述了你想要如何简化结果(参见下一节)。

增量合并开始后,你将需要解决任何必须解决的冲突。基本步骤与使用 git 进行增量合并相似

while not done:
    <fix the conflict that is presented to you>
    <"git add" the files that you changed>
    git-imerge continue

当你解决所有冲突后,通过输入以下命令完成增量合并:

git-imerge finish

这应该就足够了。所有这些子命令都有额外的选项;要了解它们,请输入

git-imerge --help
git-imerge SUBCMD --help

简化结果

当增量合并完成后,您可以使用finishsimplify命令以各种方式简化其结果,然后再将其记录到项目的历史记录中。增量合并的“目标”可以是以下之一:

  • merge — 只保留第二个分支合并到第一个分支的简单合并,丢弃所有中间合并。最终结果类似于使用

      git checkout BRANCH1
      git merge BRANCH2
    
  • rebase — 保留将第二个分支的提交版本重新应用到第一个分支。最终结果类似于使用

      git checkout BRANCH2
      git rebase BRANCH1
    
  • rebase-with-history — 类似于rebase,但保留重新应用提交的历史旧版本。它等同于将BRANCH2的提交合并到BRANCH1中,每次一个提交。换句话说,它将这个

      o---o---o---o          BRANCH1
           \
            A---B---C---D    BRANCH2
    

    转换为这个

      o---o---o---o---A'--B'--C'--D'   NEW_BRANCH
           \         /   /   /   /
            --------A---B---C---D
    

    使用这种方法重新应用已发布的分支是安全的。有关更多信息,请参阅[2]。

  • full — 完全不简化增量合并:执行所有中间合并,并将它们全部保留在永久历史中。换句话说,它将这个

      o---o---1---2---3      BRANCH1
           \
            A---B---C---D    BRANCH2
    

    转换为这个

      o---o---1---2---3
           \   \   \   \
            A---A1--A2--A3
             \   \   \   \
              B---B1--B2--B3
               \   \   \   \
                C---C1--C2--C3
                 \   \   \   \
                  D---D1--D2--D3    NEW_BRANCH
    

    这种方法保留了完整的历史和祖先信息,这为将来进行合并提供了最大的灵活性。另一方面,它在Git的永久历史中造成了相当大的混乱。

  • border — 这个实验性目标保留BRANCH2BRANCH1的重新应用,以及BRANCH1BRANCH2的重新应用,加上包含两个分支的合并提交。换句话说,它将这个

      o---o---1---2---3      BRANCH1
           \
            A---B---C---D    BRANCH2
    

    转换为这个

      o---o---1---2---3
           \           \
            A           A2
             \           \
              B           B2
               \           \
                C           C2
                 \           \
                  D---D1--D2--D3    NEW_BRANCH
    

    这种方法比简单合并或重新应用留下了更多的历史记录,可能会使未来的合并更容易。

  • border-with-history — 这个实验性目标保留BRANCH2BRANCH1rebase-with-history,以及(不带历史记录的)BRANCH1BRANCH2的重新应用,加上包含两个分支的合并提交。换句话说,它将这个

      o---o---1---2---3      BRANCH1
           \
            A---B---C---D    BRANCH2
    

    转换为这个

      o---o---1---2---3
           \           \
            A-----------A3
             \           \
              B-----------B3
               \           \
                C-----------C3
                 \           \
                  D---D1--D2--D3    NEW_BRANCH
    

    这种方法比简单合并或重新应用留下了更多历史和祖先信息,可能会使未来的合并更容易。

  • border-with-history2 — 这个实验性目标保留BRANCH1BRANCH2rebase-with-history,以及BRANCH2BRANCH1rebase-with-history,加上包含两个分支的合并提交。换句话说,它将这个

      o---o---1---2---3      BRANCH1
           \
            A---B---C---D    BRANCH2
    

    转换为这个

      o---o---1---2---3
           \   \   \   \
            A--- --- ---A3
             \   \   \   \
              B--- --- ---B3
               \   \   \   \
                C--- --- ---C3
                 \   \   \   \
                  D---D1--D2--D3    NEW_BRANCH
    

    这种方法比简单合并或重新应用留下了更多历史和祖先信息,可能会使未来的合并更容易。

技术说明

挂起/恢复

git-imerge需要用户手动进行合并时,它会创建一个临时分支refs/heads/imerge/NAME来保存结果。如果您想挂起增量合并去做其他事情然后再继续,您只需使用git merge --abort中止任何挂起的合并并切换到其他分支。当您准备好恢复增量合并时,只需输入git imerge continue

如果您需要完全中止正在进行的增量合并,首先使用git-imerge remove删除git-imerge创建的临时分支,然后使用git checkout ORIGINAL_BRANCH检查出您开始增量合并之前所在的分支。

存储

git-imerge将有关增量合并的所有中间状态记录在Git对象数据库中,作为位于refs/imerge/NAME下的一组引用,其中NAME是imerge的名称

  • refs/imerge/NAME/state指向一个blob,以JSON格式描述imerge的当前状态;例如,

    • 正在合并的两个分支的尖端

    • 当前的“阻塞”合并(用户将必须手动完成的合并),如果有的话

    • 简化目标

    • 将要写入结果的分支名称。

  • refs/imerge/NAME/manual/I-Jrefs/imerge/NAME/auto/I-J 分别表示到目前为止作为增量合并的一部分所完成的的手动和自动合并提交。 IJ 是整数,表示合并在增量合并图中的位置 (I,J)

在仓库间转移正在进行的imerge

有时可能方便将一个正在进行的增量合并从一个Git仓库转移到另一个仓库。例如,您可能想要备份当前状态,或者在家里继续您在工作中开始的一个imerge,或者请同事为您执行特定的成对合并。由于所有imerge状态都存储在Git对象数据库中,因此可以通过推送/获取上一节中命名的引用来完成。例如,

$ git push --prune origin +refs/imerge/NAME/*:refs/imerge/NAME/*

或者

$ git fetch --prune origin +refs/imerge/NAME/*:refs/imerge/NAME/*

请注意,这些命令会覆盖目标仓库中已经存在的任何状态。目前尚不支持合并两个人在增量合并上并行工作的成果,因此现在您只能轮流进行。

git rerere 的交互

git rerere 是一个很好的工具,它可以记录您如何解决合并冲突,如果在再次遇到相同的冲突时,它会尝试自动重用相同的解决方案。

由于 git-imerge 尝试了如此多的类似测试合并,因此可以想象 rerere 会感到困惑。此外,git-imerge 依赖于合并解决(或不解决)的一致性,如果它执行多次。因此,rerere 在后台存储额外信息可能会使 git-imerge 感到困惑。

实际上,在测试中,似乎在增量合并期间,git-imergererere 的交互有时会导致合并冲突被错误地解决。因此,git-imerge 在运行任何 git 命令时都会明确暂时关闭 rerere。

成对合并提交的日志消息

git imerge continuegit imerge record 在工作树中找到一个已解决的合并时,它会提交该合并并将其合并到增量合并中。通常它只是使用Git自动生成的提交消息。如果您希望被提示编辑此类提交消息,您可以在命令行上指定 --edit 或更改您配置中的默认设置。

$ git config --global imerge.editmergemessages true

测试

git-imerge 使用 tox 来运行测试。要使用系统的默认Python运行测试套件

$ tox

要使用特定的Python版本,例如3.7,向 tox 传递 -e 参数

$ tox -e py37

许可证

git-imerge 在GNU通用公共许可证(GPL)下以2或更高版本发布为开源软件。有关更多信息,请参阅文件 COPYING

参考文献

[1]

[2]

项目详情


下载文件

下载适合您平台文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源分发

git-imerge-1.2.0.tar.gz (50.3 kB 查看哈希值)

上传于 来源

构建分发

git_imerge-1.2.0-py3-none-any.whl (46.1 kB 查看哈希值)

上传于 Python 3

由以下支持

AWSAWS 云计算和安全赞助商 DatadogDatadog 监控 FastlyFastly CDN GoogleGoogle 下载分析 MicrosoftMicrosoft PSF赞助商 PingdomPingdom 监控 SentrySentry 错误日志 StatusPageStatusPage 状态页