Merge conflicts updating from upstream

15,547

Solution 1

It could be, that upstream has rewritten history (rebase, amend, …) – they shouldn't do that, but you'll never know.

Since you say you don't have any local changes or commits, you should bring your repository back to a clean state by resetting your branch:

git reset --hard upstream/allwinner-v3.0-android-v2

(This will discard any local changes and make commits of current HEAD unreachable!)


The above assumes that you will (force) push the newly reset state of your branch to your remote repository, otherwise you will encounter the conflicts again when you try to pull from origin.

git push origin +allwinner-v3.0-android-v2

If you already had committed yourself locally, you'd have to rebase (or cherry-pick) your commits on top of the upstream branch, and then do a push to origin. That way you will re-write your local history the same way upstream did and apply your changes on top, i.e.:

git rebase --onto upstream/branch \
  last-original-upstream-commit-before-yours \
  your-branch

Solution 2

The show-branch output means that upstream and HEAD have each added two commits since their common ancestor (assuming that's the full output). (See also: http://www.gitguys.com/topics/git-show-branch-to-see-branches-and-their-commits/) If you haven't committed anything yourself, that does mean that upstream pushed a rebase (or something else that changed the history). Since you haven't committed anything, knittl's answer is exactly what you want.

For what it's worth, I also love git log --oneline --graph --decorate --remotes --branches for this. You'll get an ASCII graph with all your branches and remotes, so you can visualize what happened where.

Share:
15,547
David Given
Author by

David Given

Updated on June 09, 2022

Comments

  • David Given
    David Given almost 2 years

    I'm trying to get started with git on a github project. (I've been using CVS, SVN and hg for years; git is hard to get my head around). I'm following the instructions as precisely as I can and simply cannot make it work.

    I clone my forked project:

    git clone [email protected]:davidgiven/linux-allwinner.git
    

    As recommended, I add an 'upstream' remote that tracks the project that my one is forked from:

    git remote add upstream https://github.com/amery/linux-allwinner.git
    

    I fetch from it:

    git fetch upstream
    

    All this works fine. But, it's been a week or so since I forked the project, and upstream have been making changes. So I want to pull in those changes. I'm currently in the right branch --- allwinner-v3.0-android-v2 --- so I merge from upstream into my branch:

    git merge upstream/allwinner-v3.0-android-v2
    

    ...and I get merge conflicts.

    CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby/common.h
    CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby/Makefile
    CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/standby.S
    CONFLICT (add/add): Merge conflict in arch/arm/mach-sun5i/pm/Makefile
    [etc]
    

    Now, I've checked in nothing; I haven't started work yet, and my project is completely untouched since I forked it. Therefore it should not be possible to have any conflicts. But there are some; what's going on, and how do I fix it?

    Update:

    git show-branch HEAD upstream/allwinner-v3.0-android-v2 shows this, which I have to say I don't understand a word of:

    ! [HEAD] arm: sun3i: add getioaddr macro
     ! [upstream/allwinner-v3.0-android-v2] arm: sun3i: updated irq handling and machine_desc to 3.0
    --
     + [upstream/allwinner-v3.0-android-v2] arm: sun3i: updated irq handling and machine_desc to 3.0
     + [upstream/allwinner-v3.0-android-v2^] arm: sunxi: renable early_printk in all _defconfig except crane's
    +  [HEAD] arm: sun3i: add getioaddr macro
    +  [HEAD^] arm: sun3i: add dummy machine type
    
  • David Given
    David Given almost 12 years
    I've tried that. Unfortunately it doesn't help... now git push fails, telling me that I need to git pull first; but git pull produces the same merge errors that I head before. This is actually what I'd expect; my understanding is that git reset changes the current branch to the one specified, so I now simply have a copy of upstream/allwinner-v3.0-android-v2 checked out locally as allwinner-v3.0-android-v2. But since the conflicts are happening between origin/... and upstream/..., the only thing that's changed is when the conflicts happen.
  • knittl
    knittl almost 12 years
    @DavidGiven: git push to where? It will fail, since your push is not fast-forward any more. You mention in your question that you have not committed anything, so maybe a single forced push is the way to go?
  • David Given
    David Given almost 12 years
    git push origin allwinner-v3.0-android-v2. (Which, incidentally, does precisely the same thing as a bare git push.) TBH, I want to know understand what's going on here; I don't have any commits yet, but I do want to start work on this pretty soon, so I need a general solution in case it happens again rather than a nuke-everything solution.
  • knittl
    knittl almost 12 years
    Try git pull --rebase (I think origin or upstream edited their history)
  • David Given
    David Given almost 12 years
    So: git reset --hard origin/allwinner-v3.0-android-v2 (to make sure my branch is clean); then git pull --rebase upstream allwinner-v3.0-android-v2; and... I get a very familiar set of merge conflicts. Aaargh!
  • knittl
    knittl almost 12 years
    origin/all… and upstream/all… are different branches/commits. Merging/rebasing them is likely to produce conflicts – they are different lines of development. Fetch both remotes and visualize them with gitk origin/allwinner-v3.0-android-v2...upstream/allwinner-v3.0-a‌​ndroid-v2. It's difficult to give a simple answer without knowing the exact history.
  • David Given
    David Given almost 12 years
    origin should be a direct fork of upstream --- I forked the project, waited a week, and now I'm trying to pull changes from upstream. This is why I'm confused that I'm getting conflicts. There should be nothing to conflict. upstream's changes should be applying cleanly, because origin is a copy of upstream as it was before the changes got added. And, unfortunately, while I can run gitk and see... something... I simply don't understand what I'm looking at. I think I can see that upstream has moved on two checkins since origin, but it also seems to show a checkin below origin, which is odd.
  • knittl
    knittl almost 12 years
    As mentioned in the first paragraph of my answer (and the second answer to this question), it looks like upstream has rewritten history. You have to do a reset and then force-push the history rewrite to your origin remote repo. Otherwise you keep dragging those discarded commits around (and they will continue to create merge conflicts)
  • ellotheth
    ellotheth almost 12 years
    There's a whole section on recovering from an upstream rebase in the rebase docs, it might be helpful if you want a really thorough treatment: schacon.github.com/git/…
  • David Given
    David Given almost 12 years
    Apparently history changes don't work the way I thought they did; you know, the sane way... so I finally gave in and did the reset/push, and now everything works. But I still need to know how to fix this properly; if upstream do this again while I have stuff committed, I'll be stuffed.
  • David Given
    David Given almost 12 years
    Also, if you add the push -f to your answer, I'll accept it. Thanks very much.
  • Chris
    Chris over 8 years
    I assume that the + in front of the branch name means a forced update - at least it worked for me - maybe the -f would have also worked..?
  • knittl
    knittl over 8 years
    @Chris: yes, +branchname translates to a forced push. Back then (in 2012) git push did not support the -f/--force option, it was added later.