Git rebase, skip merge-commits

前端 未结 2 676
长发绾君心
长发绾君心 2021-02-04 03:08

Starting with

    hack---F1----M1----F2  (feature)
   /            /
  C1-----C2----C3  (master)

I would like to end up with

           


        
相关标签:
2条回答
  • 2021-02-04 03:36

    Looking at your original workflow, it seems like you want to ignore merges, the only problem is using -i for an interactive rebase, which preserves merges.

    git checkout -b temp  
    git rebase --onto master hack temp
       * Big drawback is gone!
    git checkout master  
    git merge temp  
    git branch -d temp
    

    Should work exactly how you want. This probably doesn't exactly solve your "general case," though.

    0 讨论(0)
  • 2021-02-04 03:40

    Simple case

    If the state of your repo is

      hack---F1----M1----F2 [feature]
     /            /
    C1-----C2----C3 [master]
    

    and you want to arrive at

      hack---F1----M1----F2 [feature]
     /            /
    C1-----C2----C3----F1'----F2' [HEAD=master]
    

    you should use git cherry-pick, not git rebase -i (no need to juggle with interactive rebase, here):

    git checkout master
    git cherry-pick <commit-ID-of-F1> <commit-ID-of-F2>
    

    General case

    Correct me if I'm wrong, but I understand what you mean by general case as

    cherry-pick, on top of master, all the non-merge commits between hack (exclusive) and the tip of feature (inclusive).

    In the following, I'm assuming that is indeed what you mean.

    As you've rightfully noted in your comment, the approach outlined above doesn't scale very gracefully as the number of commits to manually cherry-pick increases:

      hack---F1---F2--- .... --- F68--M1---F67---...---F99 [feature]
     /                               /
    C1-------------C2---------------C3 [master]
    

    However, you can get git rev-list to automatically generate the list of revisions of interest, using

    git rev-list --reverse --no-merges --first-parent <commit-ID-of-hack>..feature
    

    Edit: you also need the --first-parent flag to avoid collecting commits such as C1 and C2, and --reverse flag, so that commits get cherry-picked in the desired order.

    You can pass the output of that command to git cherry-pick:

    git checkout master
    git cherry-pick `git rev-list --reverse --no-merges --first-parent <commit-ID-of-hack>..feature`
    

    which would yield

      hack---F1---F2--- .... --- F68--M1---F67---...---F99 [feature]
     /                               /
    C1-------------C2---------------C3---F1'---F2'---...---F99' [HEAD=master]
    
    0 讨论(0)
提交回复
热议问题