0

I was working on my dev branch, then made some commits (A, B, C). I switched to the main branch for some reason at this point, did edits on different parts of the same files I worked on before (the reason why I didn't notice that I'm on a different branch), then commited D...

* (4th) D (HEAD -> main)
|
|  * (3rd) C (dev)
|  * (2nd) B
|  * (1st) A
| /
|/
* x
* y
* z

What is the most straightforward way to have A, B, C, and D on one branch (doesn't matter if it's main or 'dev`) in the same order they have been created?

toraritte
  • 6,300
  • 3
  • 46
  • 67

3 Answers3

1

Like this:

git switch main # start at D
git branch temp # give D a name
git reset --hard @~1 # point main to x
git rebase --onto dev main temp # copy D to after C
git branch -M dev # rename D dev

Result:


   * (4th) D (HEAD -> dev)
   * (3rd) C
   * (2nd) B
   * (1st) A
  /
 /
* x -> main
* y
* z
matt
  • 515,959
  • 87
  • 875
  • 1,141
1

From main you can just run git rebase dev. That will replay everything you have in main which isn't also in dev (just D according to your diagram) onto the tip of dev.

Your main branch will then be in the state you want and your dev branch will be unchanged.

Calum Halpin
  • 1,945
  • 1
  • 10
  • 20
  • That was my first thought, but then I convinced myself that `A`, `B`, and `C`, will be put on top of `D` for some reason... Thanks! – toraritte Aug 09 '23 at 00:48
  • 1
    You'd get that if you ran `git rebase main` from `dev`. – Calum Halpin Aug 09 '23 at 00:55
  • Yeah, will have to find a mnemonic to remember the right orders. – toraritte Aug 09 '23 at 01:33
  • 1
    @toraritte The **real** solution is to **NEVER** run rebase with less than two arguments (`git rebase onto_ref branch_to_be_rebased`). So `git rebase dev main`will always, unconditionally put `main` on top of `dev` regardless of which branch was current. – hlovdal Aug 26 '23 at 20:38
0

Use git cherry-pick to move commit D from main to dev by doing the following:

  1. Find and copy the commit hash of D

  2. git checkout dev

  3. git cherry-pick <D_COMMIT_HASH>

  4. Resolve the conflicts

  5. git add <AFFECTED_FILES>

  6. git cherry-pick --continue

    At this stage, the commit history looks like the graph below,

    * (4th) D (main)
    |
    |  * (new) C_MERGED_WITH_D (HEAD -> dev)
    |  * (3rd) C 
    |  * (2nd) B
    |  * (1st) A
    | /
    |/
    * x
    * y
    * z
    

    because "technically you do not move the commit, but create a new one with the same content, and git remembers this copy when merging", so:

  7. git checkout main

  8. git reset --hard HEAD~1

toraritte
  • 6,300
  • 3
  • 46
  • 67