我有一个问题,两个类似的进程在同一存储库的不同克隆中并行运行(通常在不同的计算机上)。每次进程运行时,它都会从远程获取最新的标签,然后根据它看到的标签推断出一个唯一的数字。
例如,如果遥控器上存在这些标签: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 已放在 origin/master 上并推送。另一个进程想要将标签 1.4 放在例如 origin/master^ 上,这将涉及向后移动标签。Git 会以“非快进”错误拒绝此操作:
过程一:
$ 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
过程乙:
$ 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。
但是考虑一下这种情况:
过程一:
$ 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
过程乙:
$ 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
好的,所以我可以进行某种标准错误重定向,搜索“=”,这将允许进程 B 确定 1.4 已经在使用中。
但这有点傻。情况变得更糟:
过程一:
$ git push origin tag 1.4
Total 0 (delta 0), reused 0 (delta 0)
To /repo1
* [new tag] 1.4 -> 1.4
过程乙:
$ 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。