0

It is strange that there is merge conflict for the following steps:

  1. I forked a repo foo on GitHub
  2. I git clone this forked repo to my hard drive
  3. After 3 days, somebody committed a lot of code to a branch xyz
  4. So to make the branch exactly the same on my forked repo, I git clone again from the forked repo to a new folder bar
  5. cd bar
  6. git checkout xyz
  7. git remote add upstream <the URL for foo>
  8. git pull upstream xyz

And tons of merge conflict appeared. I never touched anything in the branch xyz. It was another developer who committed a lot of things into xyz, so the branch xyz should be just updated with all his changed, instead of having merge conflicts. Later on he said that it had merge conflicts because he git push -f and that if he never used -f, then it shouldn't have merge conflicts.

How is this situation solved?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • Perhaps the branches on the two GitHub repos diverged? – Oliver Charlesworth Jun 19 '17 at 23:36
  • `I git clone again from...` why are you cloning _again_, when all you needed to probably do is `git pull`? Are you very new working with Git? – Tim Biegeleisen Jun 19 '17 at 23:37
  • I added in the question: "I git clone again from the forked repo to a new folder `bar`". I have used git quite a bit, but that I usually don't use a forked repo, but use the original repo directly – nonopolarity Jun 20 '17 at 00:11

2 Answers2

0

You should break the pull apart into a fetch and then merge:

git fetch upstream xyz git merge upstream/xyz

Then you'll have to solve the conflicts.

Charles Durham
  • 2,445
  • 16
  • 17
  • are you sure... I heard that a fetch and then a merge, is the same as a pull... The original person who used that branch told me there were conflicts because he used `git push -f` – nonopolarity Jun 20 '17 at 02:26
0

Later on he said that it had merge conflicts because he git push -f and that if he never used -f, then it shouldn't have merge conflicts.

This is correct.

Suppose the original xyz branch looked simply like

A --- B --- C --- D

That is, there are four commits, D being the most recent. This is what you cloned.

Now, the other person force-pushes, to make the repo look like this:

A --- B --- C --- E

That is, commit D has been removed, and commit E has been added. Consider what happens when you then run git fetch:

A --- B --- C --- D  <-- local xyz branch
             `
              `--- E <-- remote xyz branch

After this is done, there is no way to determine that commit D originally came from the remote branch. It is indistinguishable from a commit that you created locally, and therefore, your subsequent git merge attempts to preserve its contents.

In this case, you want to completely ignore D, you just want to get to E. git reset --hard E will do this. You can refer to E in any of the usual ways, and the most appropriate here to me seems to be git reset --hard @{upstream}.