Combining the function correctly into the master

Problem:

I always face the same problem when it comes to multiple dependent feature branches.

master ---A---B---C
           \
feature1    D---E---F
                     \
feature2              G---H

      

I have something like this. Assuming both of these branches have been covered, I'll merge feature1

into master

. Then check and pull master

, then check and reinstall feature2

on master

. While doing this, I always see repeated conflicts over and over again, especially with multiple branches.

Good recovery:

I saw online that in the example above, I first have to do something like this to make sure I am configured correctly:

Rebase feature1

upmaster

master ---A---B---C
           \       \
feature1    \       D'--E'--F'
             \       
feature2      D---E---F---G---H

      

Rebase feature2

on new feature1

commits

master ---A---B---C
                   \
feature1            D'--E'--F'
                             \
feature2                      G'--H'

      

I would do it with git rebase --onto feature1 feature1@{1} feature2

.

Confusion:

As I understand it, it is better to reinstall this, because when you rebind, your branch will actually contain completely new commits (i.e. F

and F'

above), which can cause unnecessary conflicts.

With all this in mind, what would be the correct approach to:

  • Combine feature1

    intomaster

  • Combine feature2

    into master`

I want to try and explore the recommended approach where I can be sure that every time I have multiple dependent branches I won't accept painful conflicts.

+1


source to share


1 answer


Please note that this answer has two parts. The first is about the mechanics of rebase, and the second is about rebase vs merge.

Complex restructuring mechanics

I would do it using git rebase --onto feature1 feature1@{1} feature2

Yes: it works by splitting the argument to rebase: instead of just feature1

now it --onto feature1 feature1@{1}

.

Usually we run git rebase name

, for example git rebase feature1

. We must first git checkout feature2

. Adding feature2

to the end of the command (as above) just does the git checkout

step for us. So in the case where I call "normal" here, there is only one argument git rebase

, usually a different branch name, eg feature1

.

But what it git rebase

does is copy some commits, and for that it needs to know two things:

  • what to copy (list of commits) and
  • where to put new copies.

This one argument feature1

makes the hard climb for both of them. It's great when it works , but for a reboot feature2

to an already reinstalled feature1

it doesn't always work.

The reason it doesn't work (when it doesn't work) has to do with the graphs you drew. You drew them in a strange way, with the branch names on the left. This kind of figure is misleading: it means that every commit is on the same branch, which is simply not true.

Here's the first drawing again:

master ---A---B---C
           \
feature1    D---E---F
                     \
feature2              G---H

      

Q: Which branch has an A

on commit ? (Trick question!)

A: He is on all branches.

These diagrams should be drawn with commits on the left and labels on the right, with labels pointing to one particular commit - since these things actually work in Git. Here's the same diagram redrawn:

--A--B--C   <-- master
   \
    D--E--F   <-- feature1
           \
            G--H  <-- feature2

      

Starting at the right and next (internal and always backward) parent links from commit to commit, we can see that C

, B

and A

are on master; F

, E

, D

And A

are on feature1

; and H

, G

, F

, E

, D

and A

they are located on feature2

, for example.

Now we can draw a second diagram after the first git rebase

, for example:

          D'-E'-F'   <-- feature1
         /
--A--B--C   <-- master
   \
    D--E--F   [reflog: feature1@{1}]
           \
            G--H  <-- feature2

      



This is where the split argument goes git rebase

.

Typically Git finds a set of commits that it git rebase

copies using:

git rev-list <argument>..<current-branch>

      

which will be here feature1..feature2

. This means that all transactions are reachable from feature2

, except for all commits reachable from feature1

. Now, before we moved feature1

, this was the correct set of commits: it was H

and G

. But we moved feature1

and now this is the wrong set of commits because it includes F

back through D

too.

Once we say feature1@{1}..feature2

, we get the correct set of commits again. But now we have lost space for copying, and therefore we need --onto

: what to place the copies.

When the second rebase is over, we should do the final result like this:

                  G'-H'   <-- feature2
                 /
          D'-E'-F'   <-- feature1
         /
--A--B--C   <-- master
   \
    D--E--F   [reflog: feature1@{1}]
           \
            G--H  [reflog: feature2@{1}]

      

and since the locks are usually invisible, we can remove the bottom half of the diagram entirely.

Rebase vs merge

As I understand it is better to reinstall this, because ...

A very slippery term is best.

There are two problems with rebase:

  • It copies the commits and then leaves the originals in favor of the new copies. Does anyone else have the originals? If so, it was difficult for you too: they too have to abandon the originals in favor of new copies.

  • It copies commits. The new copies are at least slightly different from the originals (otherwise they would actually be originals). What exactly is different in copies? It is important? Did you break something in the process, that is, submit errors?

The use git merge

avoids these problems. Instead, he inserts his problems:

  • The story is confused. If it is necessary to find out what happened, then the student of history may have to look down at the "legs" of the fusion. Some argue that this is more positive than negative, because this is a real story, not a later, refined, artificial story.

    (I lean toward a cleansed story, but there are merit to both sides of this argument.)

  • The merge itself can introduce errors.

If you have a really good set of tests, it helps you deal with "inject errors" problems.

If it helps enough, it leaves only one problem with reinstallation (if you are smart enough or have a good tool to carry out your complex redistributions like this one): does anyone else have the originals? Balance your answer to this question versus your answer to the question of whether a convoluted story is bad enough to make a rebase merge decision.

If you don't have good tests, ok ... :-)

+1


source







All Articles