我有一组独立版本但彼此相关的 git 存储库。例如,在添加功能时,我可能必须向共享库添加功能,然后扩展应用程序或服务以利用该功能。
目前,我必须在处理该功能时接触的每个存储库上创建一个分支。但是,我想做的是通过一次分支和合并这些多个存储库来简化流程(以减少忘记分支或在一个存储库而不是另一个存储库中提交/合并的可能性)。
是否有一种简单的方法可以一次分支和合并多个存储库,或者这是一项更适合帮助脚本集合的任务?如果是后者,是否有任何可用的脚本已经实现了这一点?
我有一组独立版本但彼此相关的 git 存储库。例如,在添加功能时,我可能必须向共享库添加功能,然后扩展应用程序或服务以利用该功能。
目前,我必须在处理该功能时接触的每个存储库上创建一个分支。但是,我想做的是通过一次分支和合并这些多个存储库来简化流程(以减少忘记分支或在一个存储库而不是另一个存储库中提交/合并的可能性)。
是否有一种简单的方法可以一次分支和合并多个存储库,或者这是一项更适合帮助脚本集合的任务?如果是后者,是否有任何可用的脚本已经实现了这一点?
没有一种内置的方法可以同时处理多个存储库,如果你考虑一下 git 的分布式特性,除了社会约定之外,真的没有任何东西可以定义它。(考虑一下,如果有人在一个存储库中从您那里提取信息,但在第二个存储库中提取另一个远程信息 - 您能拥有这种连贯性吗?)
您可能会发现像mr这样的工具,它可以同时处理多个存储库,很有帮助。
但是,如果您确实有紧密联系的东西,我建议您将它们放入一个存储库中。这样您就不会忘记任何步骤,因为它们发生在一个原子操作中。
但是,如果您的代码实际上并没有那么紧密地联系在一起,那么放弃“必须在完全相同的时间分支”的概念,您会更快乐。
您可以使用回购工具:https ://gerrit.googlesource.com/git-repo/
没有一种内置方法可以同时处理多个存储库
但是会有的。
Git 2.27(2020 年第二季度)为“”铺平了道路,git update-ref --stdin
它学习了一些新动词,让用户更明确地控制 ref 更新事务。
这有助于作为跨多个存储库实现两阶段提交式原子引用更新的成分。
请参阅帕特里克·斯坦哈特 (Patrick Steinhardt ) 的提交 e48cf33、提交 94fd491、提交 de0e0d6、提交 804dba5、提交 5ae6c5a、提交 a65b8ac(2020 年 4 月 2 日)和提交 bd021f3、提交 faa35ee、提交 edc3069(2020 年 3 月 30 日)。(由Junio C Hamano 合并 -- --在d2ea03d 提交中,2020 年 4 月 29 日)pks-t
gitster
update-ref
:实现交互式事务处理签字人:Patrick Steinhardt
该
git-update-ref
命令现在只能通过其“--stdin
”参数处理排队事务,但用户无法以更明确的方式处理事务本身。例如,在复制场景中,可以想象
git-update-ref
为多个存储库生成的协调器,并且只有当所有人都同意可以进行更新时,协调器才会发送提交。这样的事务会话可能看起来像
> start < start: ok > update refs/heads/master $OLD $NEW > prepare < prepare: ok # All nodes have returned "ok" > commit < commit: ok
或者:
> start < start: ok > create refs/heads/master $OLD $NEW > prepare < fatal: cannot lock ref 'refs/heads/master': reference already exists # On all other nodes: > abort < abort: ok
为了允许这样的事务会话,这个提交引入了四个新命令
git-update-ref
,它们与我们内部已有的命令相匹配,除了“start
”:
start
: 开始一个新事务prepare
:准备事务,即尝试锁定所有引用并验证它们的当前值是否与预期值匹配commit
:显式提交会话,即更新引用以匹配其新的预期状态abort
:中止会话并回滚所有更改按照设计,
git-update-ref
将在标准输入关闭后立即提交。
虽然在非交易世界中很好,但在交易世界中绝对是出乎意料的。
因此,一旦使用了任何新的事务命令,默认值将更改为中止,而无需显式的“commit
”。
为了避免排队更新和第一个prepare
启动事务的“”之间的竞争,start
添加了“”命令来启动显式事务。添加一些测试来练习这个新功能。
Git 2.28(2020 年第 3 季度)和新的 hook继续采用这种同时处理多个存储库的内置方式。
请参阅Patrick Steinhardt ( ) 的提交 6754159(2020 年 6 月 19 日)。(由Junio C Hamano 合并 -- --在提交 33a22c1中,2020 年 7 月 6 日)pks-t
gitster
refs
: 实现引用事务钩子签字人:Patrick Steinhardt
用于更新引用的低级引用事务目前对用户完全不透明。
虽然在大多数用例中肯定是可取的,但有些可能希望挂钩到事务中以观察所有排队的引用更新以及观察准备好的事务的中止或提交。一个这样的用例是拥有给定 Git 存储库的一组副本,我们在其中一次对所有存储库执行 Git 操作,并期望所有存储库的结果都相同。
虽然已经存在可用于为此实现投票机制的 Git 命令的某个子集的钩子,但许多其他命令目前没有任何机制。
上述场景是直接进入 Git 的引用事务机制的新“引用事务”钩子的动机。
钩子接收事务被移动到的当前状态作为参数(“
prepared
”、“committed
”或“aborted
”),并通过其标准输入获取所有排队的引用更新。虽然退出代码在“已提交”和“中止”状态下被忽略,但“准备”状态下的非零退出代码将导致事务过早中止。
鉴于上述用例,现在可以通过此钩子实现投票机制:一旦调用它,它将获取所有标准输入并使用它对中央服务进行投票。
当存储库的所有副本都同意时,钩子将以零退出,否则它将通过返回非零来中止事务。
最重要的好处是,这将立即捕获所有写入引用的命令,从而允许通过单一机制实现引用更新的强一致性。为了测试对我们没有在存储库中安装任何“reference-transaction”钩子的情况的影响,这个提交引入了两个新的git-update-refs性能测试。
针对空存储库运行,它会产生以下结果:Test origin/master HEAD -------------------------------------------------------------------- 1400.2: update-ref 2.70(2.10+0.71) 2.71(2.10+0.73) +0.4% 1400.3: update-ref --stdin 0.21(0.09+0.11) 0.21(0.07+0.14) +0.0%
性能测试
p1400.2
创建、更新和删除一个分支一千次,因此平均运行时间git-update-refs
超过 3000 次调用。
p1400.3
而是调用git-update-refs --stdin
了 3 次,并分别将一千个创建、更新和删除排队。正如预期的那样,
p1400.3
始终没有显示出明显的影响,因为对于每批更新,都会调用一次 access(3P) 以进行负挂钩查找。
另一方面,对于p1400.2
,可以看到这个补丁集造成的影响。但是进行了五次性能测试,每次运行GIT_PERF_REPEAT_COUNT=10,
的开销都在 -1.5% 到 +1.1% 之间。这些不一致的性能数字可以通过产生 3000 个进程的开销来解释。这表明组装钩子路径和执行一次访问(3P)以检查它是否存在的开销大部分被操作系统的开销所抵消。
在 Git 2.29(2020 年第四季度)中,通过消除无效优化,简化了钩子。
请参阅Patrick Steinhardt ( ) 的提交 0a0fbbe(2020 年 8 月 25 日)。(由Junio C Hamano 合并 -- --在6ddd76f 提交中,2020 年 8 月 31 日)pks-t
gitster
refs
: 删除reference-transaction
钩子的查找缓存签字人:Patrick Steinhardt
添加
reference-transaction
钩子时,有人担心它可能会对根本不使用新钩子的设置产生性能影响。
毕竟,每次 areftx
准备、提交或中止时都会执行它,这与每个会话创建的引用事务的数量呈线性关系。
并且由于有像( man )这样的代码路径为每个要更新的引用创建一个新事务,这可能会转化为大量调用。git push
find_hook()
为了解决这个问题,添加了一个缓存,目的是不重复进行负钩子查找。
原来这个缓存导致了回归,这是通过e5256c82e5修复的(“refs
:使用引用事务钩子修复交错钩子调用”,2020-08-07,Git v2.29.0 -合并在批次 #8中列出)。在讨论修复的过程中,我们意识到即使在否定查找的情况下,缓存也没有真正的帮助。
虽然添加到基准测试中的性能测试确实显示了 1% 范围内的轻微改进,但这并不保证有缓存。
此外,它也很片状。例如,连续运行两次会产生以下结果:Test master pks-reftx-hook-remove-cache -------------------------------------------------------------------------- 1400.2: update-ref 2.79(2.16+0.74) 2.73(2.12+0.71) -2.2% 1400.3: update-ref --stdin 0.22(0.08+0.14) 0.21(0.08+0.12) -4.5% Test master pks-reftx-hook-remove-cache -------------------------------------------------------------------------- 1400.2: update-ref 2.70(2.09+0.72) 2.74(2.13+0.71) +1.5% 1400.3: update-ref --stdin 0.21(0.10+0.10) 0.21(0.08+0.13) +0.0%
这些基准测试中明显缺少的一种情况是单个可执行文件搜索挂钩数百次,这正是添加负缓存的情况。
p1400.2
将为每个事务生成一个新的更新引用,并且p1400.3
所有引用更新只有一个引用事务。
所以这个提交添加了第三个基准,它执行一千个引用的非原子推送。这将为每个引用创建一个新的引用事务。但即使在这种情况下,负缓存也不会始终如一地提高性能:Test master pks-reftx-hook-remove-cache -------------------------------------------------------------------------- 1400.4: nonatomic push 6.63(6.50+0.13) 6.81(6.67+0.14) +2.7% 1400.4: nonatomic push 6.35(6.21+0.14) 6.39(6.23+0.16) +0.6% 1400.4: nonatomic push 6.43(6.31+0.13) 6.42(6.28+0.15) -0.2%
因此,让我们完全删除缓存以简化代码。
使用 Git 2.30(2021 年第一季度),“ ( man ) ”学会在一个会话中处理多个事务。git update-ref --stdin
请参阅Patrick Steinhardt ( )的提交 8c4417f、提交 2102043、提交 262a4d2、提交 c0e1726(2020 年 11 月 13 日) 。(由Junio C Hamano 合并 -- --在提交 1bc550e中,2020 年 12 月 8 日)pks-t
gitster
update-ref
: 允许创建多个事务签字人:Patrick Steinhardt
审核人:Jeff King
虽然 git-update-ref 最近增加了允许对e48cf33b61中的事务进行交互式控制的命令(“
update-ref
:实现交互式事务处理”,2020-04-02,Git v2.27.0-rc0 --批次 #5中列出的合并),但它尚无法在单个会话中创建多个事务。为此,目前仍需要多次调用可执行文件。如果当前事务已被提交或中止,则此提交通过允许“开始”命令创建新事务来解决此缺点。
git update-ref
现在在其手册页中包含:
显式提交。当当前事务已经提交或中止时,此命令可能会创建一个新的空事务。
在 Git 2.34(2021 年第四季度)之前,“ git update-ref
” (man) --stdin
未能根据需要刷新其输出,这可能导致对话陷入僵局。
这已经修复,并且是前面提到的路径的结果。
请参阅Patrick Steinhardt ( ) 的提交 efa3d64(2021 年 9 月 3 日)。
请参阅Jeff King ( ) 的提交 7c12007(2021 年 9 月 15 日)。(由Junio C Hamano 合并 -- --在06a0eea 提交中,2021 年 9 月 23 日)pks-t
peff
gitster
update-ref
:修复状态更新流签字人:Patrick Steinhardt
当使用标志执行 git-update-ref(1) 时
--stdin
,用户可以排队更新,并且由于e48cf33 ("update-ref
: implement interactive transaction handling", 2020-04-02, Git v2.27.0-rc0 -- merge中列出batch #5 ),通过一组事务动词交互式地驱动事务的状态。
但是这种交互性有些破坏:虽然调用者可以使用这些动词来驱动事务的状态,但确认动词已被处理的状态消息不会被刷新。
因此,呼叫者可能会挂起等待确认。通过在写入状态更新后刷新标准输出来修复错误。
另外,请看一下: http: //fabioz.github.io/mu-repo/——它是一个诸如 mr 和 repo 之类的工具,因为我无法让它们按照我的需要工作:)
一些注意事项:
它是在 Python 中完成的(因此,在任何运行 Python 的操作系统中都可以正常工作:Linux、Win、Mac ......)
除了一次对许多 repos 运行通用 git 操作之外,还提供了以下工作流:
Android 存储库工具管理跨多个存储库的功能分支的创建。但是该repo upload
命令只能发布到 Gerrit 代码审查。
如果你使用 GitHub 或 GitLab 之类的普通 Git 存储库管理器,repo upload
将无法正常工作;你需要不存在的repo push
命令。我repo push
在repo 的 Wave Computing 分支中实现。我们在生产中使用它。
就像一个想法。我自己没有尝试过,但我前段时间遇到了这个功能。尝试将所有想要的存储库作为子模块添加到新的“根”存储库并使用以下命令
git submodule foreach --recursive <command>
您可以查阅有关此内容的帮助以及如何处理子模块。你可以使用任何你想要的命令。git 和非 git 命令。