1

I have some branches in git that look like:

master             b1
↓                   ↓ 
A -- B -- C -- D -- E

But D ... E turned out to be an unexpectedly nontrivial change, so I would like to see this instead:

master    b3
↓         ↓
A -- B -- C      b2
           \     ↓
            D -- E

...so that b2 can be reviewed separately, merged into b3, which is then merged to master.

I tried:

git checkout b1
git checkout -b b2
git rebase C

but got merge conflicts. That indicates to me that's that wrong way to do it, since C ... D were all applied successively to each other and should never conflict. What incantation do I need?

trbabb
  • 1,894
  • 18
  • 35

2 Answers2

3

b2 is equivalent to b1, so all you had to do was create b3 on commit C.

git branch b3 C

If you insist that b2 exists on commit E (in addition to b1) you can also just create it:

git branch b2 E

All commits in your second graph are identical to the first graph, so you don't need to do anything else.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • That makes sense. After trying it, I didn't get what I expected from GitHub (and maybe it's a GitHub specific problem)— A PR from `b2` to `b3` shows all the commits from `A ... E` instead of `C ... E` as I would expect. Is something extra that needs to be done to the repository, or should I chalk it up to a neglected UX corner case in GH? – trbabb Apr 07 '21 at 20:00
  • @trbabb When you want to submit `b2` as a PR that does not include `A`, `B`, or `C`, then you no longer have "two successive branches", but two "parallel" (so to speak) branches. Which one is it that you need? – j6t Apr 07 '21 at 20:10
  • I want to submit `b2` as a PR to `b3` (not master— yet), so the incremental changes aren't so large. Not sure if that makes sense. – trbabb Apr 07 '21 at 20:57
1

As mkrieger1 said, you literally just want to create the label b3 pointing to commit C.

The trick with GitHub and GitHub's "PR"s (pull requests) is that now that you have these names locally, you need to create the same names on GitHub—remember that their repository is in fact a separate, independent repository, with its own independent branch names—pointing to the same hash IDs. That part is easy enough: just git push origin b3 with name b3 identifying commit C locally. Since commit C (with that same hash ID) is already copied to GitHub, this just creates the name b3 on GitHub, pointing to commit C. And, that now means that on GitHub, you can create a pull request that says let's merge commit E into commit C, using names b3 as the PR and b2 as the "base branch". GitHub can only see their own names in their own repositories, but now that you did the git push, they have the same names you do.

Note that if and when the PR is approved and commit E gets merged into commit C on GitHub, this can:

  • be a true merge, or
  • be a "rebase-and-merge", or
  • be a "squash-and-merge"

but under no circumstances will the big green "merge" button on the GitHub web page create a fast-forward merge. This means you will get:

master             b3
↓                  ↓
A -- B -- C ------ M
           \      /
            D -- E
                 ↑
                 b2

if you select the "true merge" option, or:

master                 b3
↓                      ↓
A -- B -- C ---- D' -- E'
           \
            D -- E
                 ↑
                 b2

if you select the rebase-and-merge option, or:

master            b3
↓                 ↓
A -- B -- C ---- DE
           \
            D -- E
                 ↑
                 b2

if you select the "squash and merge" option.

If none of those options are acceptable (for whatever reasons—they'd be your reasons since at least some of these should work in at least some circumstances), do not use the big green merge button on the GitHub web pages.

torek
  • 448,244
  • 59
  • 642
  • 775