[英]Git strategy to minimize merge conflicts over multiple repos
外部软件供应商将产品更新作为 zip 文件的完整快照提供。 在这种情况下,它是external-base.zip
。 此外,它还提供其他几乎相同但为软件本地化版本的 zip 文件。
问题
问题是我需要对这个软件进行一些修改,同时尽量减少手动合并冲突解决。
为此,我首先创建 git 存储库ext-base
、 extLC_EN
、 extLC_GE
并在每次收到新的 zip 文件时提交给它们。
接下来,我将extBase
中的任何内容推送到intBase
中。 当我创建修改时,我将它们添加到intBase
。 每次我从extBase
推送到intBase
时,我可能会冒丢失修改的风险。
因为我希望我的修改也以本地化版本结束,所以我从intBase
推送到intLC_EN
和intLC_GE
。
=> 因此,每次当这 3 个新更新的 zip 文件到达时,我都必须解决intBase
、 intLC_EN
和intLC_GE
上的冲突,同时这些冲突的解决方案都是相似的。
注意事项
题
你能推荐我什么策略来减少工作量?
你能推荐我什么策略来减少工作量?
将您的供应商快照导入单个历史 dag,并使用您选择的分支结构(由于供应商不提供祖先,您可以自由发挥,这完全是为了您的方便)。 然后维护你自己的工作作为那些分支。
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
带有A
、 B
、 C
等标记有供应商修订号的快照。 众所周知,Git 不关心你如何做你的工作,关键是去做。
这看起来适合您所描述的设置。 你的改变是一个平行的分支结构, A'
是你在外部A
基上的改变, α'
是你A'
工作应用到α
基上,等等。 (很抱歉使用希腊语而不是格鲁吉亚字母表,这就是我所知道的)。
假设您在现有存储库中达到D
,并且拥有E
组.zip
。
工作一是构建供应商库历史记录。 工作二是构建你的补丁历史。 第三项工作是让新供应商发布舞蹈变得冷淡。
要理解的是 Git 会找到一个 repo,以及它的工作树、索引和对象数据库,如果你没有明确地告诉它,但你可以直接告诉它。 假设您有一个提取的供应商下载,看起来非常像内容快照(因为它是一个),所以告诉 Git 这是您要从中添加的工作树。
这是一个非常直接的方法。 让我们从你现有的构建历史开始,假设你到目前为止达到D
并且你没有记录任何d
,嘿,它发生了。
编辑:我很乐意充实剩下的内容,但是 (a) 我今天有事情要做,git 核心命令对某些人来说是令人反感的,以及 (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 中的子项或任何其他 ref 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 的供应商快照的重构。 现在您可以重新打包并切断联系:
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) 我有那个呃-哦-这是我的机会-真的搞砸了引用命名空间的感觉,我想要一个克隆,如果事情不顺利我可以放弃。 但在这里你将拥有
因此,让我们通过展示如何以类似方式导入现有的intXYZ
历史来积累您的rerere
目录。
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 通过注意任何新的冲突或解决方案并解决工作树中的任何旧冲突或解决方案来工作,并在其中运行索引。点亮 auto-rerere 仅意味着只要合并因冲突而停止以及提交正确的结果时git rerere
就会运行一个有冲突的合并,你可以在有用的时候自己运行它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.