简体   繁体   中英

git rebase with multiple sub-branches

I am having trouble getting git to do what I want in moderately complicated branching scenarios. It seems like some of my work is being lost whenever I use the rebase command. I am new to git, coming from a Perforce background. Am I using the wrong commands or missing some flags? Is my intuition about the internal state of my local repository correct?

Note: branchB is dependent on branchA, and branchC is dependent on branchB.

  1. git checkout master
  2. git pull master
  3. git checkout -b branchA

     ==O master \\==A branchA 
  4. edit branchA
  5. git add ...
  6. git commit
  7. git review
  8. git checkout -b branchB

     ==O==O master \\==A branchA \\==B branchB 
  9. edit branchB
  10. code review requires changes to branchA
  11. git add ...
  12. git commit
  13. git checkout branchA
  14. edit branchA
  15. git add ...
  16. git commit --amend <== should I use --amend here?
  17. git review
  18. git checkout branchB
  19. edit branchB some more
  20. git add ...
  21. git commit
  22. git review
  23. git checkout -b branchC

     ==O==O==O==O master \\==A branchA \\==B branchB \\==C branchC 
  24. edit branchC
  25. branchA passes code review
  26. git add ...
  27. git commit
  28. git checkout master
  29. git pull master
  30. git checkout branchA
  31. git rebase master branchA
  32. resolve merge conflicts
  33. git checkout master
  34. git merge branchA

     ==O==O==O==O==A master \\==B branchB <== is this correct? \\==C branchC 
  35. git checkout branchB
  36. git rebase master branchB
  37. resolve merge conflicts

     ==O==O==O==O==A master \\ \\==B branchB \\==C branchC <== is this correct? 
  38. git checkout branchC
  39. git rebase branchB branchC
  40. resolve merge conflicts <== often redo the same merge conflicts as branchB

     ==O==O==O==O==A master \\==B branchB \\==C branchC 
  41. design change requires refactoring branchA
  42. git checkout master
  43. git pull
  44. git checkout -b refactorA

     ==O==O==O==O==A master |==A' refactorA |==B branchB \\==C branchC 
  45. edit refactorA
  46. git add ...
  47. git commit
  48. git review
  49. git checkout branchB
  50. git rebase refactorA branchB <== is this a mistake?
  51. resolve merge conflicts (three sets of conflicts)

     ==O==O==O==O==A master \\==A' refactorA \\ \\==B branchB <== is this correct? \\==C branchC 
  52. git review <== complains about multiple commits
  53. git log <== shows that branchB now has a few instances of branchA's commit

You need to understand that commits are dependents from the previous one and branches are just pointers to one commit of the commit graph.

Here is the commit graph evolution, numbers are commits, upper are newer, references and branches are aside commits, HEAD is your current position.

You can see your evolution of the commit graph by launching git log --graph --oneline --all --decorate at each step.

  1. git checkout master

     1 origin/master, HEAD -> master | 0 
  2. git pull master

     1 origin/master, HEAD -> master | 0 
  3. git checkout -b branchA

     1 origin/master, master, HEAD -> branchA | 0 
  4. edit branchA

  5. git add ...
  6. git commit
  7. git review

     2 HEAD -> branchA | 1 origin/master, master | 0 
  8. git checkout -b branchB

     2 branchA, HEAD -> branchB | 1 origin/master, master | 0 
  9. edit branchB

  10. code review requires changes to branchA
  11. git add ...
  12. git commit

     3 HEAD -> branchB | 2 branchA | 1 origin/master, master | 0 
  13. git checkout branchA

     3 branchB | 2 HEAD -> branchA | 1 origin/master, master | 0 
  14. edit branchA

  15. git add ...
  16. git commit --amend => By using --amend you create a new commit with the same parent
  17. git review

     3 branchB | | 2' HEAD -> branchA | | 2 | |/ 1 origin/master, master | 0 
  18. git checkout branchB

     3 HEAD -> branchB | | 2' branchA | | 2 | |/ 1 origin/master, master | 0 
  19. edit branchB some more

  20. git add ...
  21. git commit
  22. git review

     4 HEAD -> branchB | 3 | | 2' branchA | | 2 | |/ 1 origin/master, master | 0 
  23. git checkout -b branchC

     4 branchB, HEAD -> branchC | 3 | | 2' branchA | | 2 | |/ 1 origin/master, master | 0 
  24. edit branchC

  25. branchA passes code review
  26. git add ...
  27. git commit

     5 HEAD -> branchC | 4 branchB | 3 | | 2' branchA | | 2 | |/ 1 origin/master, master | 0 
  28. git checkout master

     5 branchC | 4 branchB | 3 | | 2' branchA | | 2 | |/ 1 origin/master, HEAD -> master | 0 
  29. git pull master

     5 branchC | 4 branchB | 3 | | 2' branchA | | 2 | | | | | 6 origin/master, HEAD -> master | | | |/ / | / |/ 2 | 0 
  30. git checkout branchA

     5 branchC | 4 branchB | 3 | | 2' HEAD -> branchA | | 2 | | | | | 6 origin/master, master | | | |/ / | / |/ 1 | 0 
  31. git rebase master branchA

  32. resolve merge conflicts

     5 branchC | 4 branchB | 3 | | 2'' HEAD -> branchA | | 2 | | | | 6 origin/master, master | | | / | / |/ 1 | 0 
  33. git checkout master

     5 branchC | 4 branchB | 3 | | 2'' branchA | | 2 | | | | 6 origin/master, HEAD -> master | | | / | / |/ 1 | 0 
  34. git merge branchA # the merge is fast-forward

     5 branchC | 4 branchB | 3 | | 2'' branchA, HEAD -> master | | 2 | | | | 6 origin/master | | | / | / |/ 1 | 0 
  35. git checkout branchB

     5 branchC | 4 HEAD -> branchB | 3 | | 2'' branchA, master | | 2 | | | | 6 origin/master | | | / | / |/ 1 | 0 
  36. git rebase master branchB # 2 should be dropped as 2'' is already is the branch

  37. resolve merge conflicts

     5 branchC | | 4' HEAD -> branchB | | 4 | | | | 3' | | 3 | | | | 2'' branchA, master | | 2 | | | | 6 origin/master | | | / | / |/ 1 | 0 
  38. git checkout branchC

     5 HEAD -> branchC | | 4' branchB | | 4 | | | | 3' | | 3 | | | | 2'' branchA, master | | 2 | | | | 6 origin/master | | | / | / |/ 1 | 0 
  39. git rebase branchB branchC

  40. resolve merge conflicts # As the rebase replays all the commits in branchB history that are not in branchC history, it will replay 2, 3, 4 and 5; that why, if you had conflicts, you may encounter them again

      5' HEAD -> branchC | 4' branchB | 3' | 2'' branchA, master | 6 origin/master | / / / 1 | 0 
  41. design change requires refactoring branchA

  42. git checkout master
  43. git pull
  44. git checkout -b refactorA

     5' branchC | 4' branchB | 3' | 2'' branchA, master, HEAD -> refactorA | 6 origin/master | 1 | 0 
  45. edit refactorA

  46. git add ...
  47. git commit
  48. git review

     5' branchC | 4' branchB | | 7 HEAD -> refactorA | | 3' | | / 2'' branchA, master | 6 origin/master | 1 | 0 
  49. git checkout branchB

     5' branchC | 4' HEAD -> branchB | | 7 refactorA | | 3' | | / 2'' branchA, master | 6 origin/master | 1 | 0 
  50. git rebase refactorA branchB <== is this a mistake?

  51. resolve merge conflicts (three sets of conflicts)

     5' branchC | | 4'' HEAD -> branchB | | 4' | | | | 7 refactorA | | 3' | | / 2'' branchA, master | 6 origin/master | 1 | 0 
  52. git review

  53. git log # As you rebased your branch branchB on top of refactorA which is created from master who merged branchA, branchA commits are in branchB

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM