Suppose I have the following scenario:
o (master)
/ o--o (WIP1)
/ /
o--o--o--o--o--o (WIP2)
(X) \
o--o (WIP3)
Is there a git command which creates a new branch so that it contains the subtree after branch X? I want to perform a "large rebase", I want the three WIP branches rebased on master.
I know I can do that with some Bash scripting but I'd like to know how to do that using a git command.
There is no single git command for that. You will have to do some manual work. In your situation:
o (master)
/ o--o (WIP1)
/ /
X--o--o--B--o--o (WIP2)
\
o--o (WIP3)
You first rebase WIP1 onto master:
git rebase --onto master X WIP1
which will lead to this:
o--o (WIP1)
(master) /
o--o--o--B’
/
/
X--o--o--B--o--o (WIP2)
\
o--o (WIP3)
If you now run git rebase --onto master X WIP2
, you get this structure:
o--o (WIP1)
(master) /
o--o--o--B’
/ \
/ o--o--B’’--o--o (WIP2)
/
X--o--o--B--o--o (WIP3)
This is probably not what you want, so now you should rebase WIP2 and WIP3 on B'
:
git rebase --onto B’ B WIP2
git rebase --onto B’ B WIP3
which will lead to this:
o--o (WIP1)
(master) /
o--X--o--o--B’--o--o (WIP2)
\
o--o (WIP3)
o (master)
/ o--o (WIP1)
/ /
o--p--p--o--o--o (WIP2)
(X) (Y)
\
o--o (WIP3)
This should be a rebase --onto
(you can see one example in " How to move certain commits to another branch in git? "):
git rebase --onto master X WIP1
git rebase --onto master X WIP2
git rebase --onto master X WIP3
From Chronial 's test , that would give:
p'--p'--o--o (WIP2)
/
o-----o-----p--p--o--o--o (WIP1)
(X) (master) (Y')
\
p''--p''--o--o (WIP3)
So the first rebase is ok, but you need to get Y SHA, and:
git rebase --onto Y' Y WIP2
git rebase --onto Y' Y WIP3
I have flagged this question as duplicate. I will write what I explained the other answer but using your example.
The approach that I use for such use cases is to merge all the branches to be moved into 1 common artificial node, and then use the rebase command with the --preserve-merges
option. Merging all the branches will expose 1 end-point that will be used as the final input parameter for rebase --onto
. The start point is usually obvious, the origin of the subtree to move.
When merging to get the subtree endpoint , conflicts should be explicity avoided. Therefore the merge commands shall be instructed to solve them automatically with the -Xours
option. The merging result is not important since these artificial merge nodes will be discarded after the rebase.
It is recommended to create a new branch pack in order to not lose the original references. In the example above the following commands would be performed:
$ git checkout -b pack WIP1 # create new branch at 'WIP1'
$ git merge -s recursive -Xours WIP2 # merges WIP2 into pack (node p2)
$ git merge -s recursive -Xours WIP3 # merges WIP3 into pack
Below can be seen what the tree would become. Two new artificial nodes p2 and pack have been created with the merges.
o (master)
/
/ (WIP1) (p2)
/ o-----o-----o----o (pack)
/ / / /
o--o--o--o-----o-----o / (WIP2)
(X) \ /
o------------o (WIP3)
Now it's time to rebase. Since now there is a common endpoint for all the branches ( pack ), it's easy to move the whole subtree with:
$ git rebase --preserve-merges --onto master X pack
Which produces this:
(WIP1') (p2')
o-----o-----o----o (pack')
(master) / / /
o----o----o--o--o-----o-----o / (WIP2')
(X) \ /
o------------o (WIP3')
Now it's time to rearrange the references. I don't know why, in some cases the references are moved and in others are not. Type this for each reference WIP1, WIP2, WIP3 or whatever you need:
$ git checkout WIP1
$ git reset --hard <WIP1' hash>
And finally, get rid of the artificial commits that were created for generating a common subtree end node.
$ git branch -D pack
$ git branch -D p2 # if there is any
So the final tree would be:
(WIP1')
o-----o
(master) /
o----o----o--o--o-----o-----o (WIP2')
(X) \
o------------o (WIP3')
If you want to have this result
o (oldmaster)--o--o--B--o--o(WIP1)--o--o(WIP2)--o--o(WIP3)(master)
/
/
X
You should do this:
git rebase --onto master X WIP1 /* move WIP1 on master */
git rebase --onto WIP1 WIP2~3 WIP2 /* move WIP2 on WIP1 */
git rebase --onto WIP2 WIP3~3 WIP3 /* move WIP3 on WIP2 */
git reset --hard WIP3 /* move master index to WIP3 */
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.