Git策略可最大程度地减少多个存储库之间的合并冲突

时间:2019-12-13 15:07:21

标签: git

外部软件供应商以zip文件的形式提供产品更新作为完整快照。在这种情况下,它是external-base.zip。此外,它还提供其他几乎相同但是软件本地化版本的zip文件。


问题

问题是我需要对该软件进行一些修改,同时将手动合并冲突的解决方法降至最低。

  1. 为此,我首先创建git存储库ext-baseextLC_ENextLC_GE,并在每次收到新的zip文件时都将它们提交。

  2. 接下来,我将extBase中的内容推入intBase中。当我 创建修改,然后将其添加到intBase。每次我从 extBase改成intBase,可能会有丢失修改的风险。

  3. 我也希望我的修改也能以本地化版本结束, 我从intBase推入intLC_ENintLC_GE

=>因此,每次这3个新更新的zip文件到达时,我都必须解决intBaseintLC_ENintLC_GE上的冲突,这些冲突将是相似的。


注意事项

  1. 基本版本和LC版本的结构几乎相同。
  2. git rerere在这里有什么帮助吗?


问题

您能推荐我什么策略来减少工作量?

Depiction of repositories

1 个答案:

答案 0 :(得分:1)

  

您能推荐我什么策略来减少工作量?

将您的供应商快照导入到一个由您选择的分支结构的历史记录中(由于供应商没有提供血统,您有空余的时间,这完全是为了您的方便)。然后将自己的工作作为这些分支的分支。

  

git rerere对您有帮助吗?

为此,

git rerere ,用于简化从…任意位置合并历史记录时应用一组更改的任务。


对于要构建的供应商历史记录的具体示例,让我们使用它:

  a---b---c-------e    LC_EN  (let's say you somehow didn't import the fourth one)
 /   /   /       /
A---B---C---D---E      external-base perhaps aka master
 \   \   \   \   \
  α---β---γ---δ---ε    LC_GE

带有ABC等快照,并标有其供应商版本号。众所周知,Git不在乎如何做工作,关键是去做。

对于您所描述的设置而言,这看起来很正确。您所做的更改是并行分支结构,其中A'是您在外部A基础上所做的更改,α'是您在A'基础上进行的α工作,等等。 (很抱歉,我知道使用希腊字母而不是格鲁吉亚字母)。

假设您在现有存储库中的权限为D,并且您拥有E.zip集。


工作之一是构建供应商基础历史记录。第二项工作是构建您的补丁历史记录。第三项工作是使新供应商发行的舞蹈降温。

要理解的是,如果您没有明确告诉Git,那么Git会找到一个回购及其工作树,索引和对象db,但您只能告诉它。假设您已经提取了一个供应商下载的文件,看起来像一个内容快照(因为它是一个快照),所以告诉Git这是您要添加的工作树。

这是一种非常直接的方法。让我们从您现有的构建历史开始,假设您目前为止D,还没有记录d快照,嘿,它发生了。


edit:我很乐意补充其余的内容,但是(a)我今天要做的事情和git core命令令人反感,(b)只是思想的细节- -第一步可能足以使您走上正确的道路。询问任何令人困惑或根本不清楚的细节,我将进行更多工作。


工作一:从现有存储库中的快照构建所需的供应商基础历史记录。为了使事情简单易懂,同时又提供了一些有关Git的git-r-dun风味的信息,让我们构造一个新的统一供应商历史记录存储库。

git init /path/to/new-vendor-history      # make the unified-vendor-history repo
cd !$                                     # switch to it
mkdir -p .git/objects/info                # set it up to leech off the older histories
printf %s\\n >.git/objects/info/alternates \
   /path/to/old/{extBase,extLC-EN,extLC_GE}/.git/objects

这比为所有现有存储库添加远程控制器并获取其历史记录要快捷,便宜,您将尽早从旧的历史记录奶头中断奶,但就目前而言,请告诉Git嘿,其中有很多对象这些我现在正在使用的地方。

因为您要逐字记录extBase存储库的历史记录,所以就采用它。您已经告诉git在哪里找到对象,将当前分支(尚未指定的本地master)指向该历史记录的最快方法是

git reset -q $(git -C /path/to/old/extBase rev-parse master)  \
                                          # set my master branch to current extBase tip

现在,由于在此示例中,您需要使用现有存储库中的D,因此new-vendor-history master看起来像

A---B---C---D

因为这就是您将其重置为的内容。

因此,要完成第一个工作,是时候根据现有快照构建供应商本地化分支了。从现有的快照和一个单亲开始分支(我​​使用的是我上面绘制的提交图中的字母,实际哈希ID中的sub或任何其他引用git都可以在这里解析)

git branch LC_EN A

然后添加b树的合并

git update-ref refs/heads/LC_EN $(
        git commit-tree -p LC_EN -p B -m 'your merge message here' b:
        )

,依次类推。 b是您的extLC_EN存储库中现有的对应提交,生成的提交,您的new-vendor-base存储库中的生成提交就是我上面b所绘制的提交。

再次对LC_GE分支执行此操作,您就完成了对已经搅动的供应商快照的重组。现在,您可以重新打包并打领带:

git repack -ad
rm .git/objects/info/alternates

完成将供应商快照转换为新系统所需要做的唯一事情就是从E个下载的.zip集中添加新快照。

( cd ~/down; unzip external-base.zip )        # unpack the new snapshot
git --work-tree ~/down/external-base add .    # add to repo and update index from there
git commit                                    # commit to the current tip

( cd ~/down; unzip external-LC_EN.zip )       # unpack the new snapshot
git --work-tree ~/down/external-LC_EN add .   # add to repo and update index from there
git update-ref refs/heads/LC_EN $(            # commit to a different tip
        git commit-tree -p LC_EN -p master -m 'vendor LC_EN' `git write-tree`
        )

( cd ~/down; unzip external-LC_GE.zip )       # unpack the new snapshot
git --work-tree ~/down/external-LC_GE add .   # add to repo and update index from there
git update-ref refs/heads/LC_GE $(            # commit to a different tip
        git commit-tree -p LC_GE -p master -m 'vendor LC_GE' `git write-tree`
        )

(您可能想编写一个小脚本来分解出样板,并将供应商的版本分为提交消息,甚至如果您愿意通过三层小心地将其替换为repo-local git别名,引用雷区,尤其是 ,因为这是新供应商发布的舞蹈的第一步。


这就是工作一,繁重的工作,将您现有的结构转换并转换为单一统一的供应商历史记录工作。


第二个工作也在使您的补丁程序与新系统同步。

如果需要,可以将修补程序放在同一存储库中。我会那样做,只有在(a)我对多个独立的并发工作树有一些具体用途时,或(b)我已经知道了,这是我的机会,确实增加了refs-namespace的感觉,并且我想要一个克隆,如果事情发展的话我可以放弃。但是在这里,您将拥有

因此,通过显示如何以类似方式导入现有rerere历史记录的方式来累积您的intXYZ目录。

git config rerere.enabled true                # light auto-rerere
printf %s\\n >.git/objects/info/alternates \
    /path/to/old/int{Base,LC_EN,LC_GE}/.git/objects

现在:rerere通过注意到任何新的冲突或解决方案并解决其在其中运行的工作树和索引中的任何旧冲突或解决方案来工作。点亮自动重新启动仅意味着git rerere在合并因冲突而停止且在任何时候运行您提交了发生冲突的合并的正确结果后,就可以在需要的时候自行运行它。