我遇到了一个问题,两个类似的进程在同一个存储库的不同克隆中并行运行(通常在不同的计算机上)。每次进程运行时,它都会从远程获取最新的标记,然后根据所看到的标记推断出唯一的编号。
例如,如果远程上存在这些标记: 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放在原点/母版^上,这将涉及向后移动标记。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 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
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.4Argg!什么?吉特刚刚移动遥控器标签,没有警告!
因此,在我看来,git中的远程标记是根本失效的--它们不应该在没有明确请求的情况下“移动”。更重要的是,他们应该在默认情况下拒绝采取行动。
此外,git-tag命令应该提供一种对标记进行原子测试和设置的方法。
但是显然没有。运行git先取并不会有帮助,因为仍然存在冲突窗口,即使有冲突,在三种场景中的一种情况下,标记只是移动!
这里发生什么事情?
还有别的方法来测试和设置标签吗?
如果没有,人们如何在自动构建环境中分配和保留构建号?如何可靠地检测两个进程无意中获取了相同的版本号?
使用git 1.6.1.2。
发布于 2009-07-23 07:33:13
我认为,如果使用真正的标记对象而不是轻量级标记(更多地设计为本地标签),那么您的标签策略将是最好的。
您可以通过指定一个-a (或-m/-F)、-s或-u选项(git help tag)来创建标记对象。
尝试您的示例,但将-m "1.4 tag"添加到git tag的每次调用中。标记对象不能指导其他标记对象的后代,因此您想要在上面失败的每一个推送都会失败。
https://stackoverflow.com/questions/1169659
复制相似问题