简体   繁体   中英

Git syncing branches from branches

Let's say I've created a branch "B" off of an old tag from "A". I make some changes on "B" and open a pull request back against "A". I then make a "C" branch off of "B", which I make changes to and open a pull request, etc, until I reach branch "E".

Once I finish with my changes on "E", let's say all of these branches still have open, unmerged pull requests against "A". Since these could then be merged in any order, and "E" may have made some important changes to my original changes in"B", how do I ensure "B" has the changes from "C, D, E"; "C" has the changes from "D, E"; and "D" has the changes from "E".

Let's assume I needed to go back and make changes to A prior to any pull requests being merged, but it relied on certain changes from E.

A -----
 \
  B -----
   \
    C -----
     \
      D -----
       \
        E -----

The way you have drawn it, C has all B plus some, D has all C plus some, and E has all D plus some, so when you merge E into A , you get all of D , C , and B into A , so A will have it all.

If you say that you can merge any of B , C , D or E , in any order and ask "How will Git know what commits to merge each time"? Well, that's one of the the big ideas of git merge - git will go back and realize what has already been merged in and won't try to remerge those changes. For instance, if you merge B , which is composed of B1 , B2 , and B3 and then merge C (which is composed of C1 , C2 , C3 + B ( B1 , B2 , B3 )), then git looks at the merge history and finds all the commits that are already reached from the merge point and finds the ones that are not reached and merges those that are not reachable - that's how it knows what to merge (in this case, it would be C1 , C2 , C3 since it finds that B1 , B2 , B3 are reachable). So, internally, for instance, if you have already merged B into A and then tell it to merge C into A , git identifies the un-merged commits by doing something like git rev-list C --not A and merges those commits.The key to understanding this is to think about it like a graph and realize that git is simply trying to figure out which parts of the graph are not reachable from the merge point and the branch to be merged and those are the changes that it then wants to merge in.

If you continue on B (with B4 ) after the merge of B , that's fine, you can simply remerge branch B and it will take in just the new changes from B onto A because it does that graph traversal that I just described and realizes that B1 , B2 , and B3 have already been merged, and now its just this new B4 that it needs to merge.

The typical lifecycle of a branch created from a parent branch is that the former ends up getting merged back into the parent at some point. This concept is not limited to Git, but to development workflow in general.

In your situation, if you follow this principle it immediately resolves your problem. Here is your diagram, redrawn to be a bit more palatable:

A -----
 \
  B -----
   \
    C -----
     \
      D -----
       \
        E -----

Following the principle of merging a branch back into its parent, the order of merging should be E into D , D into C , C into B , and finally B into A . In each of these merges, there should ideally be no conflicts. If there are conflicts, they should not be due to the parent and branch stepping on each other's toes, ie both branches having worked on the same exact areas of a feature.

If your development process might require that you need to bring in the changes from E into A before rolling up all the branches in between, then you should reconsider how you create branches. In this case, you would have been better of creating branches A through E directly from the parent branch.

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