views:

21745

answers:

8

I've done 'git pull', and received a merge conflict. I know that the other version of the file is good, and that mine is bad (all my changes should be abandoned). How do I do this?

unmerged:   _widget.html.erb

You are in the middle of a conflicted merge.
A: 

From this article (way way down):

git reset --hard HEAD^
pjz
This would only be appropriate if the user wanted to throw away her last commit. The OP specified a merge that was stopped to resolve conflicts. This command would throw away the conflicted merge state and the last commit, which is not what the OP wanted.
Chris Johnsen
I agree with Chris. Git reset hard is dangerous answer to provide to an inexperienced Git user.
Alain O'Dea
A: 
git checkout _widget.html.erb

this will replace the local version of the file with the version from repository.

Bartosz Blimke
In the middle of a merge, this won't work. You'll get: error: path '_widget.html.erb' is unmerged
chrisk
+1  A: 

I think it's git reset you need.

Beware that git revert means something very different to, say, svn revert - in Subversion the revert will discard your (uncommitted) changes, returning the file to the current version from the repo, whereas git revert "undoes" a commit.

git reset should do the equivalent of svn revert, i.e. discard your unwanted changes.

David Precious
+57  A: 

Since your pull was unsuccessful then just HEAD is the last "valid" commit on your branch (not HEAD^):


git reset --hard HEAD

The other piece you want is to let their changes over-ride your changes.

Older versions of git allowed you to use the "theirs" merge strategy:


git pull --strategy=theirs remote_branch

But this has since been removed, as explained in this message by Junio Hamano (the Git maintainer). As noted in the link, instead you would do this:


git fetch origin
git reset --hard origin
Pat Notz
I apparently don't have enough karma to edit but "get reset --hard origin" should be "git reset --hard origin"
Teflon Ted
@Teflon Ted -- corrected, thanks.
Pat Notz
Instead of doing a hard reset, you could bring it to a more granular level by doing: `git fetch origin`--> `git reset origin (soft reset, your changes are still present)`--> `git checkout file_to_use_their_version_of another_file (steamroll your own changes back to match the origin)`I never use git pull any more. Since in a fight between my latest code and the origin, the origin should always win, I always `git fetch` and `git rebase origin`. This actually makes my merges and conflicts few and far between.
Tchalvak
I agree. I also like to fetch first, and then examine the upstream changes (`git log ..@{upstream}` or `git diff ..@{upstream}`). After that, like you, I'll rebase my work.
Pat Notz
+26  A: 

In this particular use case, you don't really want to abort the merge, just resolve the conflict in a particular way.

There is no particular need to reset and perform a merge with a different strategy, either. The conflicts have been correctly highlighted by git and the requirement to accept the other sides changes is only for this one file.

For an unmerged file in a conflict git makes available the common base, local and remote versions of the file in the index. (This is where they are read from for use in a 3-way diff tool by git mergetool.) You can use git show to view them.

# common base:
git show :1:_widget.html.erb

# 'ours'
git show :2:_widget.html.erb

# 'theirs'
git show :3:_widget.html.erb

The simplest way to resolve the conflict to use the remote version verbatim is:

git show :3:_widget.html.erb >_widget.html.erb
git add _widget.html.erb

Or, with git >= 1.6.1:

git checkout --theirs _widget.html.erb
Charles Bailey
thanks for the hint. doesn't this smack of a poor git user interface, though?
Peter
@Peter: I'm not convinced. The desired result is achievable with a few basic commands with simple options. What improvements would you suggest?
Charles Bailey
@Charles, I think the `git 1.6.1` command makes a lot of sense, and is good. That's exactly what I would have wanted. I think the pre-1.6.1 solution is inelegant and requires knowledge about other parts of git that should be separated from the merge resolution process. But the new version is great!
Peter
+4  A: 

If your git version is >= 1.6.1, you can use "git reset --merge"

carleeto
A: 

An alternative, which preserves the state of the working copy is:

git stash
git merge --abort
git stash pop

I generally advise against this, because it is effectively like merging in Subversion as it throws away the branch relationships in the following commit.

Alain O'Dea
I found this approach useful when I accidentally merged to a git-svn branch, which doesn't handle that nicely. Squash merges or cherry picks are better when working with git-svn tracking branches.In effect my solution turns a merge into a squash merge after the fact.
Alain O'Dea
+1  A: 

Since Git 1.6.1.3 git checkout has been able to checkout from either side of a merge:

git checkout --theirs _widget.html.erb

http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html

Alain O'Dea