1

I would like to know how to insert a new commit (commit X) between 2 older commits, but (and this is the complicated part) I would like to do it before the "branching point" (in this case commit "B").

For example:

Before:

A -- B -- C <<< master
      \
       D -- E <<< branch

After:

    new commit 
     |  
     |
A -- X -- B -- C <<< master
           \
            D -- E <<< branch

I have seen many good answers that work very well when there's no branch here :

But none of this options work when inserting a commit before the branching point, as they modify the rest of the tree "upstream" after the rebasing.

What is the best way to to this?

for context, the reason why I find myself frequently needing to do this is that when I start a new feature branch, I realise (after a few commits) that some changes should have been done earlier and on the master branch, instead of the new feature branch, like for example, modifying some .vscode files or some structural refactoring of the code that belongs more to the master branch, rather than the feature branch.

Is this the "right thing to do" in this case?

1 Answers1

2

These are all plain rebases.... set a pointer in the old B so that it's simpler to run the second rebase.

git branch old-B B

Now you have a branch called old-B pointing to the current B:

E <- (branch)
|
D
| C <- (master)
|/
B <- (old-B)
|
A

Now, take any of the recipes out there to insert X in master so that you get this (it is normally done with rebases or cherry-picks):

C <- (master)
|
B
|
X
|
A

Notice how I have eliminated branch from the chart... the branch is still there but now the full chart is really like this, actually:

C' <- (master)
|
B'
|
X
| E <- (branch)
| |
| D
| |
| B <- (old-B)
|/
A

Notice how you have the original B and a clone that is B', which is not exactly the same as the original as in now includes the changes from X

At this point, all you need to do is to place the commits in the old-B..branch range on top of B' and this can be done with this rebase:

git rebase old-B branch --onto B'

And then you get this:

C' <- (master)
|
| E' <- (branch)
| |
| D'
|/
B'
|
X
|
A
eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • Thanks for the answer! Though, could you please explain it in more detail (maybe add a more detail step by step or a line diagram like above?) I'm not sure I understand what is exactly old B and B and new-B (commit/branch) and how to exactly do this part : `Then do the rebase of the master branch to your liking. ` Sorry to bother you with this, but unfortunately I'm not sure how to try it like this :/. Many thanks for your help! – garrofederico Feb 20 '23 at 19:03
  • How would I deal with merges along the way? Say, my history contains quite a few merges and to make things even more interesting, let's assume that the merge commits also resolve conflicts. – Frederick Nord Jul 05 '23 at 12:30
  • git rebase skip merges by default. You will have to use `--rebase-merges` so that they are picked up.... and if there are conflicts along the way, git does _not_ carry over the previous conflict resolutions, you will have to redo them again (unfortunately). – eftshift0 Jul 05 '23 at 12:47