V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
James369
V2EX  ›  程序员

git 有没有必要专门拉一个分支来放标签?

  •  
  •   James369 · 2022-07-10 10:14:08 +08:00 · 4435 次点击
    这是一个创建于 872 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我看有的地方除了有一个 release 分支之外,还专门开了一个 tag 或 master 分支来放 Tag 。

    那么,为什么不直接在 release 分支上打 tag 就好了?少一个分支,这样还更省事?

    25 条回复    2022-07-18 10:51:13 +08:00
    hronro
        1
    hronro  
       2022-07-10 10:40:35 +08:00   ❤️ 2
    分支还能放 tag ???我真不理解了。。。

    「分支」可以简单理解为:指向最新 commit 的指针(即每次提交新的 commit ,分支的指针都会移动)
    「 tag 」可以简单理解为:固定指向某一个 commit 的指针

    由此可见,分支和 tag 都只和 commit 有关,分支和 tag 之间本身并没有任何的关系。专门开一个分支存 tag ,我是真不理解是怎么做到的?
    James369
        2
    James369  
    OP
       2022-07-10 10:46:25 +08:00
    BugCry
        3
    BugCry  
       2022-07-10 10:50:19 +08:00 via Android   ❤️ 1
    人多就拉,人少随意
    toast
        4
    toast  
       2022-07-10 11:14:50 +08:00   ❤️ 1
    那个就是 master 吧 = =
    M 和 P 节点上游包含哪些其他分支的节点,都是 master 的一部分的
    他就是画图的时候这么画了而已,不是说 master 只有那俩 commit
    unt
        5
    unt  
       2022-07-10 11:21:31 +08:00 via iPhone
    借楼问一下,多人协作中代码合并的规范.
    我们现在远程分支是 4 个,master,dev,adev,bdev,
    合并时 adev 和 bdev 互相合并,开发到一定阶段后一起由一个人合并到 dev 分支(个人本地会另见分支用于合并或者尝试性开发), 这种合并模式对不对
    fpure
        6
    fpure  
       2022-07-10 11:41:23 +08:00
    @unt 冗余了,保留 master 和 dev 就可以了
    hronro
        7
    hronro  
       2022-07-10 12:59:40 +08:00
    @James369 #2

    你这说的是 gitflow 之类的 GIT 工作流程吧。这和我之前说的没有任何冲突:我们在开发过程中,除了开发用的主分支外,还需要一个东西来表明哪一个 commit 可以进入测试了,哪一个 commit 已经测试通过可以部署了。而这个东西,它并不是一成不变的,会随着我们开发的推进,而不断推进。结合我上面说的,branch 是不断变化的指向 commit 的指针(会逐渐推进),tag 是不会变化的固定指向某个 commit 的指针,这里当然是使用 branch 更为合适。

    至于你说的「专门有一个分支放标签」,我估计是你对 GIT 的这些概念不熟悉导致的。实际上 Testing 、Release 这些分支,真正起作用的是分支本身,即这个指向当前分支 HEAD 的指针,用于表明这个 commit 将要被用于测试 /生产。只是这个 commit 上刚好可能有一个 tag 而已,但这个 tag 并不一定是必需的,我完全可以只从 master 分支 merge 指定的 commits 到 release 分支,一个 tag 也不打。
    zhzy0077
        8
    zhzy0077  
       2022-07-10 13:15:33 +08:00 via Android
    单一主干的没有必要 但是我给你举个例子 Windows 可能会同时有五六个在维护的版本 21H1 21H2 22H1 22H2 每个版本就需要一个单独的分支了
    虽然事实上 win 的分支管理比这个复杂很多
    securityCoding
        9
    securityCoding  
       2022-07-10 13:17:51 +08:00 via Android
    基于 commit 打 tag 就好
    pony279
        10
    pony279  
       2022-07-10 16:52:27 +08:00
    @James369
    我猜,
    这种工作流的目的是让 master 分支上面的任意一个提交都是可以发布使用的
    当出问题且无法正向解决的时候,在 master 上面直接进行版本回溯,会比在一个混杂稳定和不稳定版本的分支上操作方便很多
    直接基于 tag 进行版本回溯也是可以的,但相对没有那么直观
    yeqizhang
        11
    yeqizhang  
       2022-07-10 17:30:24 +08:00 via Android
    tag 指向提交的全局唯一版本号,只是某些分支的时间轴上可能有别的分支没合过去的提交版本号。只能说拿稳定分支上的版本号来打 tag 比较常见,说放标签就很不专业了,还专门开一个 tag 来放 tag 让人无法理解
    xiubin
        12
    xiubin  
       2022-07-10 17:59:50 +08:00
    @hronro #7

    赞同 7 楼,release 分支会因为功能或者 bugfix 合入而不断迭代,在此期间每个合入该 release 分之的 commit 都可能被打成一个 tag 进行交付或者测试。

    并不是有个 release 分支专门存 tag ,而是这个分支在迭代更新的时候出了几个版本( tag )
    chloerei
        13
    chloerei  
       2022-07-10 18:44:59 +08:00
    你可能说的是版本分支,这样一般是为了后续维护打补丁。
    GeruzoniAnsasu
        14
    GeruzoniAnsasu  
       2022-07-10 19:30:03 +08:00   ❤️ 1
    @unt
    杜绝相互合并,尤其是双向三路合并( git merge ),即 a merge b, b merge a ,which is extremely evil ;
    严格遵循单一公共线原则,即使是 feature 分支,也要有公共的 feature 分支+feature_a_dev+feature_b_dev ;
    推送代码前必须先拉代码;
    严禁任何分支 mege master ,只允许 master merge dev

    推荐在 feature 和 dev 分支上禁用 merge ,只允许 rebase 。但 rebase 会导致目标分支历史重写,所以有第二条,尽量只重写自己的分支,避免公共分支被重写干扰其他人
    GeruzoniAnsasu
        15
    GeruzoniAnsasu  
       2022-07-10 19:37:44 +08:00
    @James369

    你的理解有误,tag 就是指向具体 commit 的标签,跟在哪个分支无关

    master 分支的目的是公共 checkpoint ,包含每一个完整的 feature ,与之对应的是 dev ,会包含尚未完善的 feature 。master 上每一个 checkpoint 或者 merge 点代表完成一个完整 feature 。

    release 分支会有很多个( release_v1, release_v2 ...),它们与 master 永久分岔,目的是存放所有已发布的历史线,如果不需要对外提供旧版本的 release ,那么旧的 release 分支其实可以删掉。之所以分岔的原因是,master 会有新 feature 和新 fix ,但 release 上只会有新 fix ,历史与主线是不同的。release 上的 fix 一般通过 cherry-pick 获得

    如果完全不需要对已发布的版本做修复,而采用修复随版本滚动提供的方式,那么完全不需要 release 分支,只需要 tag/release 就好。 tag 的作用是给 commit 做特殊标记,由于有意义的 commit 一般在 master 上,所以 tag 「碰巧」打在了 master 上
    jim9606
        16
    jim9606  
       2022-07-11 00:10:20 +08:00
    你看的那个是 svn 吧,通常会分 trunk 、branches 、tags 三个目录,trunk 相当于 master ,branches 放其他稳定分支,tags 通常只从 trunk 或者某个分支 cp 出来不修改。
    THESDZ
        17
    THESDZ  
       2022-07-11 09:07:12 +08:00
    有必要,增加一点的操作成本,避免了后续的其他使用成本;
    比如热更新、回滚、版本比对等操作(各种需要一个稳定分支做动作的事情);
    以上用 tag 也行,但是不方便。
    THESDZ
        18
    THESDZ  
       2022-07-11 09:08:27 +08:00
    @THESDZ #17 其实是用分支来确定开发的不同环节,用 tag 来约束版本。
    unco020511
        19
    unco020511  
       2022-07-11 11:08:17 +08:00   ❤️ 1
    很多人连 tag 是啥都没理解,tag 是一个标记,指向某一个 commit,git 里每个 commit 都是唯一且不可变的,既然如此又何来"用分支来放 tag"的说法呢?
    我猜 op 的意思应该是说有了 dev,featureA,B,C dev 都往 dev 合,为啥还需要一个 master(或者 release)来与 dev 做同步,且在 master(或者 release)上打 tag?
    其实和各个团队规定有关系,我们团队就只有一个 rc 分支来接受合并的代码,并且在 rc 上做发布.当然如果你认为需要,dev 往 master 同步,在 master 打 tag,然后 master 作为发布分支还不是可以,没有明确规定,选择适合自己的
    tags
        20
    tags  
       2022-07-11 13:49:58 +08:00
    意思是想专门抽一些或者删除一些特性出来整成 release 版本打上 tag 吧?如果当前分支线上已经满足版本要求直接打 tag 就行了。不满足的话,比如 release 前要改一些编译配置,这些改动又不要合到主干,就会单独拉分支。
    nothingistrue
        21
    nothingistrue  
       2022-07-11 14:03:25 +08:00
    @James369 #2 他这个,release 分支是用完即删除的临时分支,长期分支只有 master 和 develop ,所以自然不可能在 release 分支上打 tag 。
    nothingistrue
        22
    nothingistrue  
       2022-07-11 14:20:25 +08:00
    @unt #5 不对。我猜你们这个 adev + bdev 混合体是丢弃历史手动合并到 dev 的(所以才需要由专门的人在专门的时间干这事)。不管 adev 还是 bdev 都是多余的,可以扔掉,用随时创建并且用完即删除的个人分支(本质上是特性开发分支或者 bug 修复分支)代替。

    git 的分支多分支协作,是一个或少量几个长期分支,加无数个临时分支构成的。长期分支越多越难管理,不要搞出 adev 、bdev 这样,仅用于合并的长期分支。另外,要想 git 协作,PR/MR ,或者补丁,最少要用到一个,不能像 SVN 那样只有更新和提交。
    heronlyj
        23
    heronlyj  
       2022-07-11 14:50:31 +08:00
    已经打 tag 了,不需要单独一个分支
    FrankHB
        24
    FrankHB  
       2022-07-11 15:49:22 +08:00   ❤️ 1
    大概就是对 tag 的用法少根筋。
    用 tag 标记 tag 主要是两个用途:传统的 release tag ,以及某个开发周期起始时的 checkpoint (鼓励一个范围内的固定起点,以避免任意位置建分支导致任何处理不同分支——包括合并——时潜在的工作量膨胀)。
    master 分支是默认分支,一般放公共主线,本来就不是放 release 用的。一般用于 release 的 tag 都是在各个 release 计划中拉出来的具体版本的 release 分支的最后的公开 commit 打,用 master 分支上面打 tag 是极端偷懒行为,几乎只适合只有一个人开发的情形。
    还有一种 tag 是专门用来做 checkpoint 的助记符。这种 tag 基本就是应该在 maintainer 负责的分支打,如果项目没多层 maintainer 那就是顶层主线也就是 master 分支。
    一些成熟的项目会明确在两者中区分,例如 GCC 迁移到 git 后就有 releases/和 basepoints/。
    原理:因为 maintainer 和某个 release 的负责人通常不总是同一位,区分 release 分支对区分责任和防止 release 阶段的提交冲突是极其有必要的。要是 maintainer 在过了 merge window 还要傻等 release branch 上的提交包括 release tag 同步却因为个别负责人的意外造成整个项目本不必要的阻塞和延期,那就真特么搞笑了。
    当然,虽然原则上限制了 DVCS 的潜力,如果中心集权到 Linus Torvalds 这样总能确保 master 上面快速发版,其他开发者会老实允许你周期性足够短地 freeze master ,那两种 tag 都塞在 master 上也不是实际不可行(像 docs.kernel.org/maintainer/rebasing-and-merging.html 建议的 merge ff 用的 tag 其实是 checkpoint )。但做不到那还就是笑话。注意虽然对组织内保持权威一般不难,但是外部开发者未必有听你话的义务,全窝在 master 上发版节奏太拉胯惹毛了外部开发者,别人直接 fork 也不是不行。
    但那个图里最大的问题还不是这个,而是临时分支居然叫 release ,成心给 release engineering 找不痛快。正常讲,这种临时分支一般都是匿名的,从来不指望不同阶段复用,非得命名也是叫 prerelease/rc 之类的。需要事后维护倒是最好约定命名,如 www.freebsd.org/releng

    @GeruzoniAnsasu 虽然相互合并通常是 evil ,但是无视分支目的教条主义更加 evil 。
    在 DVCS 中 master 分支存在的目的几乎就是全项目单一来源的全局主线(只是要实现配置管理分锅或者跨厂商管理的目的,可以 fork 整个 repo ,不需要窝同一个 origin ),因此负责人或者说 owner 大多数时都需要对其中的内容完全负责并有在整个项目中协调发布节奏的绝对权威。
    如果禁止自主 merge master 造成滞后(特别是预期就会跨 release tag 的大改动),到时候差异过大再 merge 回来,会严重阻碍中心 PM 负责人的吞吐量乃至整个项目的分支同步效率。这在上规模的(日常 master 成天管合并 PR 就够忙了)项目中是不可接受的。
    unt
        25
    unt  
       2022-07-18 10:51:13 +08:00
    @fpure #6 我这个 adevbdev 相当于是 featureA 和 featureB ,远程不建分支的话我们怎么远程备份和互相交流呢。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2730 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:45 · PVG 23:45 · LAX 07:45 · JFK 10:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.