How do I rebase a chain of local git branches?

前端 未结 4 1404
别那么骄傲
别那么骄傲 2020-12-09 09:28

Suppose I have a chain of local git branches, like this:

       master    branch1   branch2
          |         |         |
o----o----o----A----B----C----D
<         


        
相关标签:
4条回答
  • 2020-12-09 09:30

    This question is a subset of Modify base branch and rebase all children at once

    I recently started using git-chain which is a tool to solve this problem.

    Basically you specify a chain

    git chain setup -c myfeature master branch1 branch2
    

    Once this chain is set up, you can pull in commits from master, then you can run git chain rebase -c myfeature and the tool figures out all the refs and rebases everything nicely for you.

    As an added benefit, it also calculates and handles any amendments or new commits to branch1 and branch2.

    0 讨论(0)
  • 2020-12-09 09:34

    What I would have loved is for git checkout branch2 ; git rebase -i master to show me branch1 directly in the editor, and then when I save the editor, that the branch1 got updated accordingly. So I could move a commit from branch2 to branch1 directly in git rebase -i and have that "stick". Maybe with a '--rebase-branches' or something.

    So arrhhh, I share your pain.

    What I do is somwhat of a hack that mimics this missing feature. I often find that during creating long-lived branches, I keep accumulating stuff that should've gone into master before "this" branch. Fixing coding standard breaches, discovering and fixing obvious errors, documentation updates for existing code, etc. This is what I'd use your branch1 for. And then the commits that actually are part of my new feature go in branch2.

    So what I do instead of creating a branch1 branch is to create a branch1 pseudo-branch "marker" - a tiny commit that I'll throw away later with git rebase. I create it like:

    touch marker.master
    git add marker.branch1
    git commit -m "*** BRANCH1 ***" marker.branch1
    

    Now when I create commits, I mix commits that should go into master before this branch and "new" commits for this actual branch.

    When it becomes time to clean up / rebase, I git rebase -i master. Now my *** BRANCH1 *** commit is obvious in the list of commits, and I can move commits destined for branch1 up above that "line".

    Because I don't have an actual branch1 branch, git rebase master does exactly what I want, it moves branch2 and my branch1 pseudo-branch marker as one unit.

    When I'm done rebasing and am ready to push, I manually make a note of the commit ID for *** BRANCH1 ***, say abcdef1, and then:

    git checkout -b branch1 abcdef1^
    

    Then:

    git checkout branch2
    git rebase -i branch1
    

    And remove the abcdef1 commit.

    This way I can easily move commits between my branch1 and branch2 branches during git rebase -i and only actually create a real git branch1 branch at the very end.

    But oh, I'd really like for git rebase -i to do this for me!

    0 讨论(0)
  • 2020-12-09 09:40

    One-line:

    git rebase --onto branch1 branch1tmp branch2
    

    That supposes to make a branch1tmp on branch1 before rebasing branch1.

    git checkout branch1
    git branch branch1tmp
    git rebase master
    git rebase --onto branch1 branch1tmp branch2
    

    That being said, check what ORIG_HEAD references.
    From git rebase man page:

    ORIG_HEAD is set to point at the tip of the branch before the reset.

    So check if this would work (and scale better):

    git checkout branch1
    git rebase master
    git rebase --onto branch1 ORIG_HEAD branch2
    git rebase --onto branch2 ORIG_HEAD branch3
    ...
    
    0 讨论(0)
  • 2020-12-09 09:45
    git rebase master branch1
    git rebase --onto HEAD ORIG_HEAD branch2
    git rebase --onto HEAD ORIG_HEAD branch3
    # ...
    git rebase --onto HEAD ORIG_HEAD branchN
    

    I have a git alias script to do this:

    rebase-chain = "!f() { \
      for i in ${@}; do \
        git rebase --onto HEAD ORIG_HEAD $i; \
      done; \
    }; f"
    

    which can make the workflow like:

    git rebase master branch1 # start with a normal rebase
    git rebase-chain branch2 branch3 branch4 ... branchN
    

    bonus

    assuming you have bash-completion for git:

    __git_complete "git rebase-chain" _git_branch
    
    0 讨论(0)
提交回复
热议问题