Following up on Git: rebase onto development branch from upstream, basically the same ask as:
I have local
master
anddevelop
branches. I do all my work ondevelop
and then merge them intomaster
for releases. There is a remote branch,upstream/master
which has changes I want, but I want to rebase my changes indevelop
(which shares a common ancestor) on top of its changes and put them back intodevelop
. I've already donegit fetch upstream
.
Here is the (a bit more complicated/advanced) situation I'm facing with, starting from scratch.
- I forked an upstream, and made my own changes from its development branches (
dev/br-1
), in my own new branch (dev/br-2
), andgit push
to my own repo. - Now, upstream has advanced, both in its
master
anddevelop
branches. - The way upstream advanced its
develop
branch is viarebase
, i.e., all its own changes are put back on top after rebase. - My local repo is gone with my old machine, and I need to pick-up/git-clone from my own repo to continue with my customization.
- I want to rebase my changes in my
dev/br-2
branch (which shares a common ancestor) on top of all the upstream changes. - I've already done
git fetch upstream
and was able to rebase mymaster
with upstream's. - It is how to rebase my current
dev/br-1
from upstream, thendev/br-2
fromdev/br-1
branch that makes my head spinning nonstop.
Although it looks like a very specific case, but the principle of how to do git branching and rebasing still applies, and the answer would be very educational to the general public. Please help.
UPDATE: So I looked at @torek suggested git rebase --onto
command, like How to git rebase a branch with the onto command?, and all their refed docs, and think my problem is still one or two levels up than what I've read (because there are two repos and 5 branches involved). Here is the summary:
Situation at point#1:
A---B---C---D master (upstream)
\
E---F---G dev/br-1 (upstream)
\
H---I---J dev/br-2 (myown)
Situation at point#2&3:
A---B---C---D master (upstream)
\
E'---F'---G' dev/br-1 (upstream)
And I don't even know where should I draw my myown
branch. Here is my current situation (which may have already been messed up, as I see HEAD
might be in a weird place):
$ git log --all --decorate --oneline --graph
* 7aec18c (upstream/dev/br-1) more updates
* b83c3f8 more updates
* 4cf241f update file-a
* 200959c update file-a from main
* dc45a94 (upstream/master, master) update file-a from main
| * ce2a804 (origin/dev/br-2) update file-a
| * 0006c5e (HEAD -> dev/br-1, origin/dev/br-1) more updates
| * cdee8bb more updates
| * 85afa56 update file-a
|/
* 2f5eaaf (origin/master, origin/HEAD) add file-a
The ultimate goal is to place myown
H---I---J dev/br-2
branch on top of the newly rebased G'
, in my own repo, after catching up with upstream. I.e., in my own repo, in the end, it should look like this:
A---B---C---D rebased master (upstream)
\
E'---F'---G' rebased dev/br-1 (upstream)
\
H'---I'---J' rebased dev/br-2
How to do that?
More explain by command:
cd /tmp
mkdir upstream
cd upstream
# prepare its `master` and `dev/br-1` branches
cd /tmp
git clone upstream myfork
# prepare my own changes based on the `dev/br-1` branch into `dev/br-2`
cd /tmp/upstream
# advance its `master`
. . .
# and its`dev/br-1` branches
git checkout dev/br-1
git rebase -X theirs master dev/br-1
. . .
Now upstream has advanced, both in its master
and its develop
branches (via rebase
), and I need to pick-up from my own repo to continue with my customization.
cd /tmp
mv myfork myfork0
git clone myfork0 myfork1
cd myfork1
git remote -v
git remote add upstream /tmp/upstream
git remote -v
git fetch upstream
git rebase upstream/master
git checkout --track origin/dev/br-1
$ git remote -v
origin /tmp/myfork0 (fetch)
origin /tmp/myfork0 (push)
upstream /tmp/upstream (fetch)
upstream /tmp/upstream (push)
$ git branch -avv
* dev/br-1 0006c5e [origin/dev/br-1] more updates
master dc45a94 [origin/master: ahead 1] update file-a from main
remotes/origin/HEAD -> origin/master
remotes/origin/dev/br-1 0006c5e more updates
remotes/origin/dev/br-2 ce2a804 update file-a
remotes/origin/master 2f5eaaf add file-a
remotes/upstream/dev/br-1 7aec18c more updates
remotes/upstream/master dc45a94 update file-a from main
$ git log --all --decorate --oneline --graph
* 7aec18c (upstream/dev/br-1) more updates
* b83c3f8 more updates
* 4cf241f update file-a
* 200959c update file-a from main
* dc45a94 (upstream/master, master) update file-a from main
| * ce2a804 (origin/dev/br-2) update file-a
| * 0006c5e (HEAD -> dev/br-1, origin/dev/br-1) more updates
| * cdee8bb more updates
| * 85afa56 update file-a
|/
* 2f5eaaf (origin/master, origin/HEAD) add file-a
UPDATE2:
With above status, when I tried --rebase-merges
as suggested by @VonC, I'm getting:
$ git rebase --rebase-merges --onto master $(git merge-base dev/br-2 master) dev/br2
fatal: Not a valid object name dev/br-2
fatal: invalid upstream 'dev/br2'
$ git checkout --track origin/dev/br-2
Branch 'dev/br-2' set up to track remote branch 'dev/br-2' from 'origin' by rebasing.
Switched to a new branch 'dev/br-2'
$ git rebase --rebase-merges --onto master $(git merge-base dev/br-2 master) dev/br-2
Successfully rebased and updated refs/heads/dev/br-2.
$ git log --all --decorate --oneline --graph
* 344418c (HEAD -> dev/br-2) update file-a
* 4de3dec more updates
* 81af2ac more updates
* 1e3f9fb update file-a
| * 7aec18c (upstream/dev/br-1) more updates
| * b83c3f8 more updates
| * 4cf241f update file-a
| * 200959c update file-a from main
|/
* dc45a94 (upstream/master, master) update file-a from main
| * ce2a804 (origin/dev/br-2) update file-a
| * 0006c5e (origin/dev/br-1, dev/br-1) more updates
| * cdee8bb more updates
| * 85afa56 update file-a
|/
* 2f5eaaf (origin/master, origin/HEAD) add file-a
Here, how to rebase my current dev/br-1
from upstream, then dev/br-2
from dev/br-1
branch please
(detailed preparation can be found at https://pastebin.com/Df8VbCp2, if necessary).