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

萌新请教 Git Rebase 问题

  •  1
     
  •   353943780 · 2020-08-05 15:37:55 +08:00 · 4582 次点击
    这是一个创建于 1601 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近项目新功能在 feature 分支开发中,突然要修复一些 bug,所以开了 fixbug 分支

    请问修复之后的 commit 如何 rebase 到 feature 分支保持干净?

    1 -> 2 -> 3 -> 6 -> 7 feature 分支
    1 -> 2 -> 3 -> 4 -> 5 fixbug 分支

    理想中 rebase 之后的 commit

    1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7

    35 条回复    2020-08-06 11:31:08 +08:00
    dsdisenc
        1
    dsdisenc  
       2020-08-05 15:40:09 +08:00
    git checkout feature
    git rebase fixbug
    这样顺序就是 1234567 了
    353943780
        2
    353943780  
    OP
       2020-08-05 15:41:54 +08:00
    @dsdisenc 请问如果是

    1 -> 2 -> 3 -> 4 -> 5 feature 分支
    1 -> 2 -> 3 -> 6 -> 7 fixbug 分支

    效果也是一样的么?
    gesse
        3
    gesse  
       2020-08-05 15:50:19 +08:00
    feature 上的 4-5 和 fixbug 上 6-7 并没有严格的先后顺序

    不管是 rebase 还是 merge,其实都是“合并代码”的过程
    rproud
        4
    rproud  
       2020-08-05 15:50:49 +08:00   ❤️ 14
    来玩个游戏你就会了。https://learngitbranching.js.org
    353943780
        5
    353943780  
    OP
       2020-08-05 16:05:46 +08:00   ❤️ 2
    @rproud 学习了
    gesse
        6
    gesse  
       2020-08-05 16:15:30 +08:00
    rebase 怎么理解呢?

    比如
    分支 a 是 1-2-3
    分支 b 是 1-2-4-5

    在分支 b 上 rebase a 分支的意思是:
    以 a 分支为"base",然后把“相对于 a 分支不同的 commit (也就是 4-5 )”加到 a 分支的后面,然后合并后( rebase 也要合并,因为在 a 分支上创建 b 分支后,a 分支也有修改的内容)的这个 branch 重新定义为 b,且 a 分支不变
    353943780
        7
    353943780  
    OP
       2020-08-05 16:26:51 +08:00
    @gesse

    分支 a 是 1-2-3-4-6-8
    分支 b 是 1-2-5-7

    请问如果分支上 commit 时间并行这样的话,是不是完全合并为单条时间线呢?
    hmxxmh
        8
    hmxxmh  
       2020-08-05 16:44:44 +08:00
    @rproud 这个太棒了
    luxinfl
        9
    luxinfl  
       2020-08-05 17:13:11 +08:00
    小小的吐个槽,feature 分支的数字应该比 fixbug 分支小才对。。
    fan123199
        10
    fan123199  
       2020-08-05 17:17:10 +08:00 via Android
    如果 featuea 的 commoit 数已经特别多了,可以考虑用 cherry pick 。不然有冲突就难受了。
    353943780
        11
    353943780  
    OP
       2020-08-05 17:32:05 +08:00
    @luxinfl 数字代表时间先后顺序喔,可能是并行开发新功能跟修 bug
    353943780
        12
    353943780  
    OP
       2020-08-05 17:34:28 +08:00
    @fan123199 请问如果 feature commit 多,而且 commit 时间点与 fixbug 交错,例如

    feature 1-2-3-4-6-8-9-10
    fixbug 1-2-5-7

    是不是无法 rebase 为单条时间线呢?
    JJstyle
        13
    JJstyle  
       2020-08-05 17:48:05 +08:00
    用 cherry-pick,简单易用:

    ```bash
    git checkout -b feature_tmp 3

    git cherry-pick 4^..5
    git cherry-pick 6^..7

    git branch -d feature
    git branch -m feature
    ```

    虽然操作步骤多一点,但是更易于常人理解!
    GeruzoniAnsasu
        14
    GeruzoniAnsasu  
       2020-08-05 17:48:47 +08:00
    跟时间没关系

    checkout feature, rebase bug ==> 125734689
    checkout fixbug, rebase feature ==> 12346891057
    JJstyle
        15
    JJstyle  
       2020-08-05 17:54:39 +08:00
    #13 cherry-pick 也能只 copy 一个 commit,上面的例子没显示出来,比如:

    ```bash
    git cherry-pick 7
    ```

    这样就把 commit 7 copy 到当前分支了,如果多个就是 a..b,前开后必区间,所以如果 copy a 到 b,且包含 a 和 b,那就用 a^..b
    pegasusz
        16
    pegasusz  
       2020-08-05 17:54:51 +08:00
    @rproud 这个也太 Q 了
    353943780
        17
    353943780  
    OP
       2020-08-05 17:58:39 +08:00
    @GeruzoniAnsasu 大佬,刚刚试了一下,rebase 之后确实跟时间没有关系 👍,但是发现 rebase 之后 push,有提示 pull,但是 pull 之后会自动产生一个 commit 是 merge fixbug 分支的,请问这样的情况怎么处理呢?
    353943780
        18
    353943780  
    OP
       2020-08-05 18:01:26 +08:00
    @JJstyle 好的大佬,我试试哈
    luxinfl
        19
    luxinfl  
       2020-08-05 18:30:16 +08:00
    @353943780 不是说再开发新 feature,然后突然发现有 bug 么。。。
    ScepterZ
        20
    ScepterZ  
       2020-08-05 18:56:16 +08:00
    按理说你的 fixbug 应该要 merge 到 master 吧
    mrege 之后
    git checkout feature
    git rebase master
    然后变成
    1 2 3 4 5 6new 7 new
    GeruzoniAnsasu
        21
    GeruzoniAnsasu  
       2020-08-05 18:56:23 +08:00
    @353943780 我们假设一个场景是 checkout fixbug 然后 rebase 了 feature

    照之前的例子,本地历史被改成了 1-2-3-4-6-8-9-10-5-7
    但此时远程的 fixbug 历史还是 1-2-5-7,两边不一致
    所以你想直接推的时候会提示要合并远程
    如果此时你先 pull 的话就会变成 1-2-3-4-6-8-9-10-5-7-merge,然后 merge commit 的两个 parent 分别是远程的 7 和你本地的 7,原本单历史线就会不必要地变成双线+合并历史,比较混乱

    所以此时不要管远程,直接 force push 让你本地的单线历史覆盖远程的就行,反正远程的 5 和 7 两个 commit 在你准备推的历史线里都是有的



    rebase 完经常是要 force push 的,确认本地 rebase 前已经完全同步了远程并且 rebase 后远程没有新 commit 就行
    force push 用 git push --force-with-lease
    353943780
        22
    353943780  
    OP
       2020-08-05 19:27:27 +08:00
    @GeruzoniAnsasu 👍👍 学习了,牛皮啊大佬
    creanme
        23
    creanme  
       2020-08-05 19:29:59 +08:00
    @JJstyle 想请教一下, 如果没法保证 commit 不包含多余的东西,是不是没法用 cherry pick ?
    HangoX
        24
    HangoX  
       2020-08-05 19:42:49 +08:00
    我一般都是
    ```bash
    git checkout feature
    git merge --squash fixbug
    ```
    直接把 bug 那个变成一条提交加到 feature 上来就好了
    fan123199
        25
    fan123199  
       2020-08-05 20:34:23 +08:00
    @GeruzoniAnsasu #21 。有个前提,这个是 fixbug 是你一个人使用的分支的情况下才可以这么用。其实 force 操作总归是危险的。
    johnsona
        26
    johnsona  
       2020-08-05 20:53:23 +08:00
    结合 pycharm 的 git rebase 可视化解决冲突食用,更加愉快
    ljpCN
        27
    ljpCN  
       2020-08-05 21:39:58 +08:00 via Android
    @353943780 从第一个不同的数字开始,后面的时间顺序已经没有意义了。任意 rebase 即可。
    365473321
        28
    365473321  
       2020-08-05 22:14:26 +08:00
    我的理解:其实 rebase 就是修改 commit 记录,还没提交到 remote 的 commit 在本地怎么折腾都行,squash 、fixup 、cherrypick,甚至 force push,怎么舒服怎么来,无非就是让历史记录看起来舒服一些。如果是多人开发,本地的 commit 又在 remote 上,老老实实用 merge 。
    no1xsyzy
        29
    no1xsyzy  
       2020-08-06 10:08:38 +08:00
    同上,而且 Github 工作流的类比,任何 bugfix 的分支最后也应该是 merge 进主线的。
    julyclyde
        30
    julyclyde  
       2020-08-06 10:09:32 +08:00
    rebase 就是把 merge-base 点向前推进了
    raysonlu
        31
    raysonlu  
       2020-08-06 10:40:38 +08:00
    之前我也在纠结这个 rebase 功能,但我发现很难把控这个(或者我未理解透彻其背后运作)。最后还是决定用回 merge,在处理类似 fixbug 分支,我心目中是要保留这个分支信息的,就是要看到:在某一点另辟蹊径,修复了问题,然后合并回归到主线。merge 的时候加上--no-ff 就好了。
    GeruzoniAnsasu
        32
    GeruzoniAnsasu  
       2020-08-06 10:58:08 +08:00
    @raysonlu rebase 这个命令其实意义有点误导,它应该叫 git modify-history

    移动 commit 到其它分支,调整 commit 顺序,修改 commit 信息,修改 commit 作者,修改内容

    全都可以借助 rebase

    个人感觉 rebase 的本意是调整当前分支的 base,像拉拉链一样移动缝合点,但实现这个效果得把当前 base 后的所有 commit 都接到另一个地方去,相当于一次性移动修改多个 commit,然后又因为反正都要修改,不如顺便能修改 commit 历史……结果就变成了一个啥都能干的命令

    git reset 和 git rebase 是 git 里最意义不明的两个 sub command
    johnsona
        33
    johnsona  
       2020-08-06 11:13:38 +08:00
    1.git rebase 是变基操作,feature 1-2,bugfix 从 feature 分出来,提交是 1-2-3,这时候切换回 feature,再提交一个,变成 feature 1-2-4
    这时候如果在 feature 合并 bugfix 会变成 1-2-( 3,4 )-5,提交历史是双线,不是很清晰,怎么办呢,我们可以让 feature 分支基于 bugfix 分支,这就是 git rebase,过程是首先找到两个分支的共同祖先 1-2,然后再 feature 分支上 copy3 提交,然后提交 4`这 4‘和 4 的 hash 值不一样了,只是修改一样而已。然后当然如果 3-4 冲突了,还是要解决冲突,但最后的结果还是 1-2-3-4`,就是一条直线了,而且和提交时间无关,就是把 bugfix 的不同提交插入 feature 分支的 2 后面
    2.解决冲突可配合 pycharm 使用,可视化更加方便,否则文件中一堆》》》
    johnsona
        34
    johnsona  
       2020-08-06 11:25:52 +08:00
    我的应用场景是这样。我们不允许本地直接提交 develop 分支,都是拉下来 develop 分支,创建 feature 分支,然后 push 到远程 feature 分支,然后远程提 pr 要求合并到 develop,给别人 review 。这时候就有个问题了,我不能在别人 review 的时候 block 在那里啊,如果幸运的话,我的 feature 分支通过了,会合并到 develop 分支,所以我本地得从 feature 分支 checkout 一个 feature2,然后继续开发。
    问题来了,如果我的远程的 feature 分支要修改,比如 feature 现在是 1-2,远程也是 1-2,但我要修改本地变成 1-2-3,但是这个 feature 就变成了 2-3 两次提交,一次任务两次提交,不好在 web 界面对比和 develop 的变化,所以我要在本地合并 2 、3 提交,变成 4,就是 1-4 了,这时候远程还是 1-2,没办法,git push origin feature -f 强制提交。
    又有问题来了,feature2 刚刚还是切换过来还是 1-2 呀,这可怎么办,如果 git merge feature 就分叉了,这时候就可以用 git rebase 让 feature2 以 feature 为基,变成 1-4-2’,看起来就像是从最新的本地 feature 分支切换过来,又加了一次提交,当然这个 2‘已经不是原来的 2’了,hash 值也不一样了。这样的好处是,如果 feature 远程合并到了 develop 远程,develop 提交记录就是 1-4,你的 feature2 再合过去就不会有冲突了
    johnsona
        35
    johnsona  
       2020-08-06 11:31:08 +08:00
    git rebase 的应用场景还包括,合并提交,比如我的 feature 变成了 1-2-3,2-3 是一次任务的两次提交,要合并成一个,怎么办,可以先 git reset soft 到 1 这个位置,然后把暂存区的 commit 一次,变成 4,就合并成功了。也可以 git rebase 。
    至于 bug,一般是先从 develop 分出来一个 bug 分支,然后修改,一次提交,合到 develop,这时候 feature 分支原来也是从 develop 分出来的,肯定也有这个 bug,所以要把这个 bug 的提交也再 feature 上面重放一次,记住是重放,提交哈希值是不一样的,一般用 cherry-pick 。当然你也可以 git rebase 基于最新的 develop,让那个 bug 的提交插入到 develop 的提交和你的 feature 提交之间
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1992 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 16:14 · PVG 00:14 · LAX 08:14 · JFK 11:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.