我有一个问题,两个相似的进程在同一个存储库(通常在不同的计算机上)的不同克隆中并行运行。每次进程运行时,它都从远程获取最新的标记,然后根据所看到的标记推断出一个唯一的数字。
例如,如果远程设备上存在这些标签:1.0 1.1 1.2 1.3
然后一个进程将选择1.4作为下一个数字。
在进程开始之前,它会创建一个新标记并将其推回到远程:
$ git tag 1.4 HEAD
$ git push origin tag 1.4
这个
主意
这是一种原子选择数字的方法。另一个进程,如果同时查看,也可能决定使用1.4,但是当它推送它的标签时,它应该发现1.4已经存在,并选择1.5(然后重试)。
我希望我能把git标签推送看作原子的。
不幸的是,由于一些奇怪的原因,Git允许远程标签在某些情况下移动!
例如,假设标签1.4已放在原点/主节点上并被推送。另一个进程希望将标签1.4放在origin/master^上,这将涉及向后移动标签。Git将以“非快进”错误拒绝此操作:
进程A:
$ git tag 1.4 origin/master
$ git push origin tag 1.4
Total 0 (delta 0), reused 0 (delta 0)
To /repo1
* [new tag] 1.4 -> 1.4
进程B:
$ git tag 1.4 origin/master^
$ git push origin tag 1.4
To /repo1
! [rejected] 1.4 -> 1.4 (non-fast forward)
error: failed to push some refs to '/repo1'
好的,没关系,过程B可以用这个来尝试1.5。
但考虑一下这种情况:
进程A:
$git tag 1.4源站/主服务器
$git推送源站标签1.4
总计0(增量0),重复使用0(增量0)
对/进行1
*[新标签]1.4->1.4
进程B:
$ git tag 1.4 origin/master
$ git push origin tag 1.4
Everything up-to-date
哦。真遗憾-Git没有指出这个标签已经存在于远程。实际上,它是这样的,用-v:
$ git push origin tag 1.4 -v
Pushing to /repo1
To /repo1
= [up to date] 1.4 -> 1.4
Everything up-to-date
好的,所以我可以做一些stderr重定向,搜索“=”,这将允许进程B确定1.4已经在使用中。
但那有点傻。更糟的是:
进程A:
$ git push origin tag 1.4
Total 0 (delta 0), reused 0 (delta 0)
To /repo1
* [new tag] 1.4 -> 1.4
进程B:
$ git push origin tag 1.4
Total 0 (delta 0), reused 0 (delta 0)
To /repo1
fd0e09e..c6cdac9 1.4 -> 1.4
阿尔格!
什么?Git没有警告就移动了远程标签!
所以在我看来,Git中的远程标签基本上是被破坏的——它们不应该在没有明确请求的情况下“移动”。更重要的是,他们应该默认地拒绝搬迁。
此外,git tag命令应该提供一种原子测试和设置标签的方法。
但显然没有。首先运行git fetch没有帮助,因为仍然有一个冲突窗口,即使有冲突,在这三个场景中的一个,标签也会移动!
这是怎么回事?
有没有其他方法来测试和设置标签?
如果不是,人们如何在自动构建环境中分配和保留构建编号?当两个进程无意中获得相同的内部版本号时,如何可靠地检测?
使用Git 1.6.1.2。