V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
git
Pro Git
Atlassian Git Tutorial
Pro Git 简体中文翻译
GitX
tlerbao
V2EX  ›  git

开源项目二开如何让 git 不分叉。

  •  
  •   tlerbao · 2020-12-20 20:07:42 +08:00 · 5038 次点击
    这是一个创建于 1466 天前的主题,其中的信息可能已经有所发展或是发生改变。

    某个项目来自于开源项目的二次开发

    项目本身有两个 remote

    origin : 该项目我自己的私有 remote

    upstream : 依赖的开源项目本身的 remote

    项目有两个分支 master 和 dev,dev 用来开发,master 分支只合并 dev 上线分支。

    现在是大部分时候我和 upstream 开源项目作者可能同时进行开发,如果我本地没有任何 commit 还好,一旦我本地有若干 commit (甚至已经合并到 master 并且已经 push 了)之后,我此时从 upstream 开源项目 pull 最新代码下来合并后,git log 就会分叉,并且会产生多余的一条 commit:Merge branch 'master' of https://xxx into dev 。

    请问有办法避免分叉和产生这个多余的 commit 吗? rebase 似乎不行,求大神指教 另外这是我的强迫症作祟,如果能避免,避免分叉真的好吗,还是我无病呻吟 应该改掉这个强迫症,继续让他保持分叉。

    30 条回复    2020-12-21 11:19:35 +08:00
    msg7086
        1
    msg7086  
       2020-12-20 20:15:03 +08:00   ❤️ 2
    你用 merge pull 当然会产生 merge 。用 rebase 就行了。
    tlerbao
        2
    tlerbao  
    OP
       2020-12-20 20:16:31 +08:00
    @msg7086 具体一点小哥,我似乎用 git pull --rebase 也不行
    ysc3839
        3
    ysc3839  
       2020-12-20 20:17:47 +08:00 via Android
    @tlerbao git rebase upstream/master
    saberlong
        4
    saberlong  
       2020-12-20 20:21:18 +08:00 via Android
    简述书上有个"如何使用 Git Rebase",我觉得不错
    nightwitch
        5
    nightwitch  
       2020-12-20 20:23:45 +08:00
    https://learngitbranching.js.org/?locale=zh_CN

    建议把这个里面和 rebase 有关的章节都练习一下,自能解惑
    msg7086
        6
    msg7086  
       2020-12-20 20:26:23 +08:00
    首先,我相信你是在做类似 mod 一样的工作。
    这样的话,你所有的修改,应该都是在 upstream 上追加,对不对。
    那么假设有 upstream 版本 v1,然后你在上面加了一堆 commit 做成了 v1mod 。
    看上去是这样:
    v1
     ↳ v1mod

    现在 upstream 更新到了 v2
    v1 → ...... → v2
     ↳ v1mod

    那这里就很简单啊,你签出 v2,然后把 v1mod 上所有的提交搬过去不就得了。
    v1 → ...... → v2
     ↳ 旧 v1mod  ↳ 搬走的 v1mod


    最后应该是类似这样的结构:
    https://vip1.loli.net/2020/12/20/R9Juo3MjUqgidTy.png

    你不如先看看你的下游分支是不是结构干净整洁。不整洁的分支历史是很难处理的。
    msg7086
        7
    msg7086  
       2020-12-20 20:28:09 +08:00
    shawndev
        8
    shawndev  
       2020-12-20 20:32:23 +08:00
    不如换一个思路,将原始项目作为 submodule,你的所有修改导出为 patch 文件。
    hantsy
        9
    hantsy  
       2020-12-20 20:42:04 +08:00
    我是日常使用方式:

    上游的项目 Fork 到你账号。

    git clone github.com/your/project

    git remote add origin your project url
    git remote add upstream upstream project url

    同步:(我的本地 Master 只作同步,相当只读方式)
    git checkout master
    git pull upstream master
    git push origin master

    feat 开发:
    git checkout master // make sure you are branching from master.
    git checkout -b feat1
    git commit -am "feat: my feat"

    gh pr create // use Github CLI to push to my origin/feat and create PR base on upstream/master

    // 可能再次 Commit
    git commit -am "commit"

    //合并上面的没 Push 的 Commit
    git commit --amend -am "commit "

    //可能 push 了, 再次 Commit
    git push -u
    git commit -am "another commit"

    //想合并一些 Comment,重整一下 Commit log 。
    git rebase -i Head~3

    //上游 Master 太多更新了,想同步一下。
    // 先按上面的 同步 说明,切换到本地 Master,上游 Master 更新到本地 Master,Push 到 origin/master, 切换回 feat1
    git rebase -i master

    //最后你的 Pr 合并到上游
    //可以是 Rebase (没冲突),也可能是 Merge (+Squash )
    gh pr list
    gh pr merge 55
    liuxey
        10
    liuxey  
       2020-12-20 20:54:58 +08:00
    核心就是 变基( rebase ) ,好好研究一下吧,rebase 的使用姿势很多
    tlerbao
        11
    tlerbao  
    OP
       2020-12-20 21:15:27 +08:00
    @msg7086
    @ysc3839
    @saberlong
    @nightwitch
    @msg7086
    @hantsy
    @liuxey

    我看了下简书那个如何使用 rebase 有点收获,我现在是 在 dev 分支这样操作
    首先 git pull --rebase upstream master,没冲突最好,有冲突合并,或者还未 commit 的冲突先存储
    成功 pull 后然后 rebase 到 master
    git rebase master
    然后
    git checkout master && git merge dev
    然后 push master

    这样似乎我的时间线清楚了也没有分叉,但是在 git log 的时候,上游的 log 好像还是出了一个小叉这是正常的把,入下图

    https://talent-miaoqiang.oss-cn-hongkong.aliyuncs.com/markdown/20201220/D1UA54.png
    YouLMAO
        12
    YouLMAO  
       2020-12-20 22:26:19 +08:00 via Android
    好好用 git,不要提一些不合理要求,rebase 不建议在生产的仓库使用,个人玩耍就随便
    cnnblike
        13
    cnnblike  
       2020-12-20 22:33:58 +08:00 via iPad
    @YouLMAO 没明白,我们工作的主 repo 有大概几百个 commit,历史两年多,rebase 用得好好的,另一个历史更长
    saberlong
        14
    saberlong  
       2020-12-20 22:44:42 +08:00 via Android
    @tlerbao
    确实会存在。rebase 方案这个地方确实不完美。只要分支开发提交到上游就会有。确认没问题后,删除这个分支也不影响。但是一般会保留用于追溯。由于基变导致 commit log 编号不同,需要靠 commit 说明来对比。虽然有瑕疵对比 merge 方案,我更喜欢 rebase 。
    saberlong
        15
    saberlong  
       2020-12-20 22:47:05 +08:00 via Android
    @tlerbao 另外多个分支并行开发时。rebase 方案操作步骤会更多,我会使用本地临时分支
    YouLMAO
        16
    YouLMAO  
       2020-12-20 22:47:43 +08:00 via Android
    @cnnblike 为了追求 Git 的线好看,在团队合作中使用 rebase 说轻点是舍本逐末,说重了是对团队不负责任。个人玩耍项目无所谓。非 Apache 项目不管你。
    saberlong
        17
    saberlong  
       2020-12-20 22:58:23 +08:00 via Android
    @tlerbao 另外要说明的是,团队使用 rebase 方案,需要培训和约束的。否则请用 merge 方案。
    msg7086
        18
    msg7086  
       2020-12-20 23:33:15 +08:00   ❤️ 1
    @YouLMAO 菜不是弃用一个优秀功能的理由。
    Git 线好看怎么就是舍本逐末了。版本管理系统里,「版本管理」自然就包括对历史的把控。一个清晰的历史记录可以方便地追溯代码的变更,也方便把某个或者某组提交拿出来做 revert 或者 cherry pick 。
    因为某些开发人员水平太菜,导致该 rebase 的地方滥用 merge,最后版本管理记录变成一大坨犬牙交错的屎山,这才叫舍本逐末,这才叫不负责任。
    不懂可以去学,可以让同事教,没人会怪你的。

    怎么不说因为有些人写不好 C++所以大家都去改用 VB6 呢。

    当然,还有一种可能,你们团队太大了,不可避免地遇到坑队友而且没人愿意培训。
    这种情况下最好的方法既不是 rebase 也不是 merge,而是 squash 。
    我们团队现在就是推荐用 squash,虽然主线上一坨坨的 squash 谁都不知道里面到底有哪些东西,但是老板开心就好了呗,反正出问题也轮不到我背锅,我一点儿也不想操心。
    msg7086
        19
    msg7086  
       2020-12-20 23:38:04 +08:00
    @tlerbao #11 你这个看上去不太对。
    rebase 完以后应该是一条直线,像是:
    e723 → 1219 → 你的项目的 4 次提交

    你看我 7 楼贴的图,upstream (mainline) 到 mod (sb-master) 之间应该是一条线。
    ooee2016
        20
    ooee2016  
       2020-12-21 00:28:45 +08:00 via iPhone
    YouLMAO
        21
    YouLMAO  
       2020-12-21 00:38:16 +08:00 via Android
    @msg7086 我有一个 Apache 项目 pmc,不知道比你的小多少
    msg7086
        22
    msg7086  
       2020-12-21 01:31:15 +08:00
    @YouLMAO 其实我不太明白你提 Apache PMC 和你提出的团队里用 Rebase 是对团队不负责任有什么关系。
    在我看来,Good practice 应该是对团队负责任的行为,只不过是因为需要妥协一些现实中无法解决的情况(例如队友太菜)而不得不采取变通的措施。
    从你前面的观点,即「用 Rebase 」→「对团队不负责任」这个论点来看,我觉得有两种可能。
    1. 你觉得 Rebase 让版本历史保持清晰不属于 Good practice ;
    2. 你觉得 Good practice 是对团队不负责任的行为。
    你想说的是其中的哪个呢?

    我司姑且不算很小,但是我不代表我司发言,所以就不报名号了。
    但是我司要求每个 MR 都使用 Squash 方式合并,这样既不会有 Merge 也不会有 Rebase 。
    说白了只是为了省事,省得培训每个员工罢了。
    我自己的个人项目是不会去用这么 low standard 的做法的。
    ooops
        23
    ooops  
       2020-12-21 02:00:26 +08:00
    PR/MR 没 merge 之前随便 rebase,有什么好纠结的。如果开发分支也多人协作那就定好了标准,做 rebase 完就即时同步给小伙伴就可以了。你 rebase,他也 rebase 没有太多问题。稍微配合下 cherry-pick 让提交历史好看一些也是不错的。
    合并之后再改历史是大忌。
    cnnblike
        24
    cnnblike  
       2020-12-21 02:14:47 +08:00
    @YouLMAO 这不就典型的菜怪工具不好用么? squash+rebase 逻辑很清晰的,git blame 一下整个历史清清楚楚
    cnnblike
        25
    cnnblike  
       2020-12-21 02:19:53 +08:00
    squash+rebase 之后拿工具就可以方便的检测出整个系统的依赖关系,通过把 interface 写在一个独立的 repo 里面,可以很方便的实现多个 pipeline 同时自动回滚,如果是多个 branch merge 过来的话,回滚到哪个 branch 的哪里去?
    chchwy
        26
    chchwy  
       2020-12-21 09:29:04 +08:00
    rebase 唯一解答,只要在本地端還沒推送上去的內容,沒有什麼理由不能 rebase 。
    hantsy
        27
    hantsy  
       2020-12-21 10:00:13 +08:00   ❤️ 1
    @tlerbao 你这样用,本地 Master 还是 Origin Master,还是 Dev 分支内容都是一锅粥。现在你看到只是自己一个人的几次提交 Log,等你在项目有多个人的时候,提交了几个月再去看你的 Log 吧。

    我使用的原则:我的 Master (本地或者 Origin 上)尽可能与 Upstream Master 致。每次创建分支前,都是必须要同步操作,保持与上游一致。

    而且我的经验是是大部分情况下,我的开发分支不需要中途 Rebase,绝大多数情况下,在 PR Merge 的选择 rebase 是可以合并进 Upstream Master 的(冲突的时候,直接在 Github Web 界面上修改冲突,合并即可)。Git 不仅仅是配置管理一部分,分支与任务颗粒度大小匹配,这与软件开发管理经验和实实在在软件架构的设计也很大关系,尽可能是一个分支对应的任务快速完成( 4 小时到一天内最好,超过了一天,就应该考虑这个 Issue 是不是包含太多的内容),而且有清晰依赖关系(不要依赖没完成的任务)。

    这个 Flow 不是我发明的,Github 最初版本的 Flow 包含这个步骤的。只是现在看到的 Github Flow 版本官方教程,省略了 Fork,简化了很多。而 Fork 在 Github 最初的理念正是体现了 Social Coding 。
    Achieve7
        28
    Achieve7  
       2020-12-21 10:15:40 +08:00
    我一般是本地 rebase 一遍 rebase -i, 然后 Squash, 最后再推上去 主干永远是一条线
    Achieve7
        29
    Achieve7  
       2020-12-21 10:15:52 +08:00
    @msg7086 很难不资瓷
    geying
        30
    geying  
       2020-12-21 11:19:35 +08:00
    git stash
    git fetch
    git stash pop
    git push
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4463 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 10:07 · PVG 18:07 · LAX 02:07 · JFK 05:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.