1

My git history looks like this:

 A     B    main
 |     |    | 
 *     |    |
 *     |    |
 *     |    |
   \   |    |
     \ |    |
       *    |
       *    |
        \   |
          \ |
           \|

What I want something like this:

B   main A
|  |   |
|  |   |
|  |   |
|  |   |
|  |   |
|  |   *
*  |   *
*  |   *
\  |  /
 \ | /

When I tried rebasing A onto main, it rebased B. The main issue is that I have things on A, that are dependent on B, but I would like to keep those changes on B. Is this possible?

Thanks in advance.

  • 1
    Your graph is not precise to give you the right advice but what you want to use is `git rebase --onto` feature: https://medium.com/@gabriellamedas/git-rebase-and-git-rebase-onto-a6a3f83f9cce – Philippe Mar 07 '23 at 20:05
  • If there are things in A that depend on B, it doesn't really make sense to rebase A on main. (At least, not without brining the commits from B along with it.) – chepner Mar 08 '23 at 18:48

2 Answers2

1

So redrawing with named commits so it is possible to refer to them individually.

  a3 - <A>
   \
    a2
     \
      a1
       \  b2 - <B>
        \ |
         b1 
          \ 
           m35 - <main>
            |
           m34
            |
           ...

What you want is

  a3' - <A>
   \
    a2'
     \       b2 - <B>
      a1'     |
       \     b1
        \   /
         m35 - <main>
          |
         m34
          |
         ...

where a1' is commit a1 rebased on top of main but excluding the changes from commit b1, etc.

This is as Phillip commented a prime use case for rebase --onto, namely in this case

git rebase --onto main b1 A  # where "b1" is the actual commit id for commit b1

PS When running (non-interactive) rebase you should exclusively use the 2 or 3 argument form.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
0

You need to do an interactive rebase to the last commit on main in A.

So on branch A find the commit where it diverges from main by git merge-base main branchA

Now do a interactive rebase to that SHA git rebase -i <SHA>. You should get a list of commits including the two on B that you don't want. Remove those commits from the list. Now Git should apply the commits and you will have the history that you want.

Schleis
  • 41,516
  • 7
  • 68
  • 87
  • That makes sense, thanks! Just one more question: What happens to changes in commits on A that depend changes on B. I would like to leaves those on B. Is that possible? – tommasopeduzzi Mar 08 '23 at 07:11
  • Commits don't really work like that. They are a snapshot of the state of the repository, the diff is the changes that are needed to go from one commit to another. So they don't really "depend" on each other per se. – Schleis Mar 08 '23 at 15:24
  • Ah, I've always thought that commits are changes, not snapshots... Thanks for clearing this up! – tommasopeduzzi Mar 13 '23 at 15:51