Reputation: 773
I have my master branch master
and a branch originalCode
. The parent of the originalCode
branch is master
:
F originalCode
/
A - B - C - D - E master
Now I want to move my originalCode
branch with commit F
before the commit A
.
I already tried around with rebasing and merging, but I could not get it to work and I could not find a similar question regarding this.
The goal is to have a common history to see exactly what changes from the original code (some scripts) have been made. When I started with checkin in, I already started with an external modified version.
Upvotes: 1
Views: 875
Reputation: 23144
Here's how I would do it:
Create and switch to a new branch reordered
, which will later contain the reordered commits, to point to the same commit (F
) as originalCode
:
$ git checkout -b reordered originalCode
The commit graph now looks like this:
F originalCode, reordered
/
A - B - C - D - E master
This is so that master
and originalCode
remain untouched. In case something goes wrong, you can simply delete reordered
and start over.
Interactively rebase reordered
, positioning F
before A
:
Since A
is the root commit, you need to specify the --root
option.
$ git rebase -i --root reordered
This will open a text editor containing something like this:
pick d14a5dd A
pick 57b6bd9 B
pick de4e672 C
pick 6fc8c1f D
pick 453da48 E
pick d2443c0 F
Cut the line with F
and paste it above the line with A
. Then save and exit the editor to continue.
Depending on the actual contents of your commits, you may need to resolve merge conflicts during the rebase.
Once the rebase is done, the commit graph should look like this:
F originalCode
/
A - B - C - D - E master
F'- A'- B'- C'- D'- E' reordered
Note that there are two series of commits that have no common ancestor, because of the --root
rebase.
Reassure yourself that there are no differences in content between reordered
and master
.
$ git diff reordered master
This should produce no output.
(Edit: I suspect you want the contents of master
as the "newest" version, not the contents of originalCode
, so I changed the diff
accordingly.)
If there is a difference, you may have done something wrong while resolving merge conflicts.
You may also inspect the individual commits using a graphical repository browser like gitk
.
Once you are satisfied with the state of the reordered
branch, you can either delete originalCode
and master
, followed by renaming reordered
to master
, or you can move master
to point to the same commit (E'
) as reordered
and delete the originalCode
and reordered
branches.
$ git checkout -B master reordered
$ git branch -D reordered originalCode
The end result should be a commit graph like this:
F'- A'- B'- C'- D'- E' master
To address the concerns raised by some commenters:
In case there are other people who have cloned the repository and depend on the master
branch, you should not delete or move it like shown in step 5 above.
Instead (after step 4) I would propose to merge the new reordered
branch into master
, to provide an alternative history leading to the current state, but keeping the original history as well:
$ git checkout master
$ git merge reordered
$ git branch -d reordered
Result:
A - B - C - D - E - G master
/
F'- A'- B'- C'- D'- E'
Upvotes: 3
Reputation: 13387
You do the following:
Create a new root commit containing the original code base:
git checkout originalCode
git checkout --orphan originalCode2
git commit -m "Original code of project foo"
Now we have to transplant the history leading to master
on top of this new root. For this purpose, we graft commit A
on top of originalCode2
:
echo $(git rev-parse A originalCode2) >> .git/info/grafts
and then rewrite the history to make the new parentship permanent:
git filter-branch master
Now you have the intended history. Note that this rewrites history and all caveats concerning published rewritten history apply.
Finally, you should remove the last line of .git/info/grafts
(which was written in the above steps). It is most probably the only line, then you can just remove .git/info/grafts
.
It may be possible to use git rebase --root originalCode2 master
or some variation involving --root
instead of filter-branch
, but I have no experience with this rebase variant.
Upvotes: 0