Why git rebase shows conflicts in the files I did not modify?

后端 未结 1 1083
遥遥无期
遥遥无期 2021-02-04 07:24

Let\'s say that I am on a local repo and its branch is my_name/branch_A

When I do git rebase , I sometimes get many conflicts i

1条回答
  •  余生分开走
    2021-02-04 07:58

    Rebase copies commits (and then abandons the originals). This is the root of the problem.

    Let's look at an example. First, note that I'm drawing commit graphs with older commits towards the left, and newer commits towards the right. The commits have single-letter names here, instead of Git's true 40-character hash names like f1c93ab7.... Branch names appear on the right, with an arrow pointing to the tip commit of that branch, because that is how Git actually stores these things.

    Your current branch name is my_name/branch_A, and you have a branch named branch_B as well. There are some commits on each branch that are not on the other branch, and some commits that are on both branches. Meanwhile your branch, my_name/branch_A, forks off from some third point—so there are commits on your branch that are not on branch_B, but are not "your commits":

    ...--A--B--C--D--E         <-- branch_uhoh
             \        \
              \        I--J    <-- my_name/branch_A
               \
                F--G--H        <-- branch_B
    

    You made commits I and J and now you would like to have those two commits come after commit H, i.e., to rework your commits to be "after" the tip of branch_B.

    In other words, you did not make commits C--D--E. Nonetheless, these commits are on your branch. In fact, commits A and B are on your branch too: those two commits are on all the branches.

    If you now run git rebase branch_B (while you're still on your branch), Git has to figure out two things:

    • what to copy, and
    • where to start putting the copies.

    The name branch_B tells Git both of these things. The commits to be copied are "those that are on my_name/branch_A but not on branch_B. That's C-D-E-I-J. The place to put them is "after the tip commit of branch_B, i.e., after commit H.

    If this all succeeds, Git would set your branch name to point to the new copies:

    ...--A--B--C--D--E         <-- branch_uhoh
             \        \
              \        I--J    [abandoned]
               \
                F--G--H        <-- branch_B
                       \
                        C'-D'-E'-I'-J'  <-- my_name/branch_A
    

    The names with the "prime" marks (C' and so on) are the copies.

    (You can view the commits that git rebase would/will copy with git log ..HEAD, which in this case is git log branch_B..HEAD. I would add --oneline here in most cases to get a one-line log message per commit.)

    Well, if that's the problem, what should you do? The obvious answer is: tell Git not to copy C-D-E. You want this result instead:

    ...--A--B--C--D--E         <-- branch_uhoh
             \        \
              \        I--J    [abandoned]
               \
                F--G--H        <-- branch_B
                       \
                        I'-J'  <-- my_name/branch_A
    

    That is, Git should copy only those commits "between" (after, really) the tip of branch_uhoh and your branch, so as to get commits I and J; but it should copy them to (again, after, really) the tip of branch_B. The way to do that is to write:

    git rebase --onto branch_B branch_uhoh
    

    In other words, tell rebase both things, instead of telling it one thing and letting it figure out the two from that.

    (But how do you find branch_uhoh? Well, the "right" way is usually to remember it, but you can just run git log --graph --decorate --oneline and find the cutoff commit by its ID or any name that shows up. Instead of branch_uhoh you can cut-and-paste the hash ID of the actual cutoff commit. Most often, you can have Git itself remember the "upstream" name for you, and you rebase only within and onto the upstream and you need no arguments: you just run git rebase and it does all the work. But there are special cases where you need to transplant commits, where this is not sufficient; then you need git rebase --onto.)

    0 讨论(0)
提交回复
热议问题