git - Git 策略以最小化多个 repos 的合并冲突
问题描述
外部软件供应商将产品更新作为 zip 文件的完整快照提供。在这种情况下,它是external-base.zip
。此外,它还提供几乎相同的其他 zip 文件,但都是软件的本地化版本。
问题
问题是我需要对这个软件进行一些修改,同时尽量减少手动合并冲突解决。
为此,我首先创建 git repositories
ext-base
,extLC_EN
,extLC_GE
并在每次收到新的 zip 文件时提交给它们。接下来,我将里面的任何东西推
extBase
入intBase
. 当我创建修改时,我将它们添加到intBase
. 每次我从 推extBase
入intBase
,我都可能冒着丢失修改的风险。因为我希望我的修改也能在本地化版本中结束,所以我从和推
intBase
入。intLC_EN
intLC_GE
=> 所以我必须解决intBase
, intLC_EN
, 和intLC_GE
每次这 3 个新更新的 zip 文件到达时的冲突,而这些冲突的解决方案始终是相似的。
注意事项
- 基本版和 LC 版具有几乎相同的结构。
- git rerere在这里有什么帮助吗?
问题
你能推荐我什么策略来最小化工作?
解决方案
你能推荐我什么策略来最小化工作?
将您的供应商快照导入单个历史 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
s。
工作一是构建供应商基础历史。工作二是构建你的修补历史。工作三是让新供应商发布的舞蹈冷下来。
要理解的是,如果你不明确地告诉它,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 在哪里可以找到对象,将当前分支(尚未指定的 local 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 或任何其他 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 repack -ad
rm .git/objects/info/alternates
完成将供应商快照转换为新系统剩下要做的唯一事情是从下载E
的.zip
s 集中添加新快照。
( 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) 我有那个 uh-oh-here's-my-chance-to- 时,我才会制作单独的 repos真的-screw-up-the-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 的工作原理是注意到任何新的冲突或解决方案,并解决工作树中的任何旧冲突或解决方案,并在其中运行它的索引。点亮 auto-rerere 仅意味着git rerere
每当合并因冲突而停止时运行,并且每当您提交冲突的正确结果时运行合并,你可以在有用的时候自己运行它。
推荐阅读
- python - 条件重采样以获得月平均值
- node.js - 如何阻止量角器下载最新的 chromedriver?
- math - 对偶数求和的方案函数
- php - PHP PDO登录系统失败
- pandas - 用分组值替换列数据
- asp.net - 尝试从服务器端打开 RadWindow 时,在 Javascript 中出现错误为“空引用”
- soundcloud - SoundCloud 应用程序注册表已关闭
- android - linearLayout 的位图不会占据整个屏幕,直到子视图停止。为什么?
- jquery - 移动到根目录后损坏的 WordPress 管理布局
- django-rest-framework - Elastic Beanstalk 无法响应请求,即使它不受资源限制