Reputation: 2219
I've got a git repo that I would like to restructure completely.
All in all I've got three features, let's call them feature A
, B
, C
, that I've been working on for the past few weeks. Unfortunately I've been a bit unthoughtful regarding how to use branches to split my working on the features correctly, and I somehow also jumped from feature to feature even between commits.
So now I've got three branches A_devel
, B_devel
, C_devel
and in each branch a bunch of commits that belong to each of the three features. Some commits of feature A
also containing some changes for feature B
in B_devel
, some of B
with changes for A
in C_devel
and so on. Some commits are even in the master
branch, containing changes for any of the features. And all the commits are also already pushed to origin
.
It's a complete chaos...
... that I would like to clean up now.
At least I can see from the commit messages and in some cases just from the code diffs what I've been working on in every particular commit. So I know which commit belongs to which feature. I just need to know how to actually move the commits to the corresponding correct branch.
//edit: by the way, I have to mention that I'm the only one working on this repo, locally as well as on origin. So most likely no one would have problems with a changed history... just in case that's going to be necessary.
Upvotes: 1
Views: 121
Reputation: 18869
Please note the following before reading the rest of the answer:
So my suggested strategy would be something as follows. Consider the following structure which has a mish-mash of changes related to features A and B on two branches:
A1--A2--B1--B2--A3 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B3--B4--A4--B5 (B_Devel HEAD)
what we want is:
A1--A2--A3--A4 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B1--B2--B3--B4--B5 (B_Devel HEAD)
Copy all commit related to feature A to A_Devel from B_Devel:
git checkout A_Devel
git cherry-pick A4
giving
A1--A2--B1--B2--A3--A4 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B3--B4--A4--B5 (B_Devel HEAD)
git checkout B_Devel
git cherry-pick B1 B2
giving
A1--A2--B1--B2--A3--A4 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B3--B4--A4--B5--B1--B2 (B_Devel HEAD)
git checkout A_Devel
git rebase -i HEAD~~~~
(we wanna remove B1, B2)
pick B1
pick B2
pick A3
pick A4
Delete the first two lines and save and exit from editor. Wait for rebase to finish.
Now we'll have:
A1--A2--A3--A4 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B3--B4--A4--B5--B1--B2 (B_Devel HEAD)
Similarly, for branch B_Devel:
git checkout B_Devel
git rebase -i HEAD~~~~~~
(we wanna change stuff in the last 6 commits)
pick B3
pick B4
pick A4
pick B5
pick B1
pick B2
delete the line with A1 and reorder the remaining 'B' changes so that they look like:
pick B1
pick B2
pick B3
pick B4
pick B5
Save, exit, wait for rebase to finish which will finally give us:
A1--A2--A3--A4 (A_Devel HEAD)
/
o-o-X (master HEAD)
\
B1--B2--B3--B4--B5 (B_Devel HEAD)
Upvotes: 1
Reputation: 1381
Definitely not a nice solution, but if you're going through the whole log, you could theoretically use a combination of git cherry-pick <commithash>
to get one commit from one branch to another one, and git rebase -i
(interactive rebase) to reorder commits in your branch.
Upvotes: 1