简体   繁体   中英

steps to take when rebasing a branch thats branched off a branch which is branched off a main branch

I keep getting nightmare rebases and I think its because Im taking the wrong steps.

I've got 3 branches... mainbranch, branch1, branch2... branch1 is a branch off mainbranch... branch2 is a branch off branch1

branch1 is 1 commit ahead of mainbranch branch2 is 1 commit ahead of branch1

So its in this state that I have problems when I... git fetch -p; git pull -r... on mainbranch I now want to bring the new changes on mainbranch into branch1 and branch2. This is what I am currently doing:

git checkout mainbranch
git fetch -p
git pull -r
git checkout branch1
git rebase -i mainbranch (i dont squash commits or anything like that)
git checkout branch2
git rebase -i branch1 <<< this causes the problem

When I run that last command I have a nightmare with conflicts. I am assuming because somehow when i did the first rebase in the steps above that it messed with the commit hashes and has confused git. What steps should I take to do this correctly? thanks

The goal here is to end up in the initial state (branches 1 commit ahead of each other) but with all the changes from mainbranch in all the branches

pull -r rebases the new commits from your mainbranch , so they really get new hashes, and this makes git recognize them differently. I'm not sure how much text changes affect this behavior (I guess they do the most), but this (only?) can happen when rebasing commits that modify the same files. What you need is only to tell git to rebase the branch1 and branch2 branches with their single commits (I'm assuming this is clear from your question) because git does not track them itself.

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git rebase --onto mainbranch branch1~1 branch1

# rebase branch 2
git rebase --onto branch1 branch2~1 branch2

Note that the rebase commands tell git to start rebasing according to these rules:

  • --onto <base> tells git where to start building new commits onto ( --onto mainbranch and then --onto branch1 )
  • <upstream>~1 tells git the range/number of patches to be applied from (literally one only)
  • <downstream> tells git the branch name to rebase

So, it's something like "git please rebase the branch branch1 onto the current mainbranch , only one ( ~1 ) patch please", and then the same for the branch1-branch2 rebasing.

It might be easier to track down why it gets happening when using interactive rebase (at least you can see what causes that):

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git checkout branch1
git rebase -i mainbranch
# note that the editor opens with more than one command: two or more picks (depends on the number of commits on main branch)
# simply remove all commands except the last `pick` command that picks the only commit from the branch1 branch

# rebase branch 2
git checkout branch2
git rebase -i branch1
# the same here: note that this will also include the original commit from branch1 that should be dropped too
# keep the last `pick` command only

Once it's done, in both scenarios (you decide which you prefer to follow), git log --oneline would produce something like:

CCCCCC (branch2) the only commit from branch2
BBBBBB (branch1) the only commit from branch1
AAAAAA (mainbranch) the tip commit at mainbranch
...

If you're familiar with what happens there and you feel safe with doing rebases and understand that something may go wrong, you can then even do something like:

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git rebase master
git rebase --skip # assuming conflicts will occur here
                  # and this is equivalent to dropping the current patch from the interactive rebase (scenario 2 above)
                  # or excluding the commit from the commit range (scenario 1 above)
# possibly more `git rebase --skip` (unless the only patch is applied)

# rebase branch 2
git rebase branch1
git rebase --skip # one time than the previous rebase because of the old "branch1 commit on branch2" commit

I prefer the last one because I can see it right in my bash prompt (number of patches to apply, aheads/behinds after the rebase is completed, etc), but I always double check the result using git log before force-pushing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM