I did git stash save
then git pull
git stash pop
and now I have conflicts and I want to reset one file to be the same as from pull to remove changes from stash (I have other changes in other files that I wan to keep).
I've tried:
git checkout -f inst/app/server.R
but got warning:
warning: path 'inst/app/server.R' is unmerged
and the file is unchanged, I still have conflict markers inside. How can I checkout that file from last commit?
TL;DR: It sounds like you want git checkout --ours inst/app/server.R
.
You are in the middle of a conflicted merge, so there are two "last commit"s. One is your HEAD (current) commit. Note that your current commit is the one you were on when you ran your command, unless your command is git rebase
, in which case things get swapped around: see What is the precise meaning of "ours" and "theirs" in git? Since you say the last command, the one that failed with a merge conflict, was git stash apply
,1 your current commit is the one you made after your git pull
ran a successful git merge
for you,2 and the other commit is one of the several commits in your current git stash
stash-bag under the name stash@{0}
(aka just stash
).
(There is a third commit involved in any conflicted merge, which is the merge base. It's probably less relevant for stashes, which are a bit weird, but it is worth mentioning. Note that if you set merge.conflictStyle
to diff3
in your Git configuration, you will get the merge-base version with an extra set of conflict markers, |||||||
, between the <<<<<<<
and >>>>>>>
sections showing you the "ours" and "theirs" versions. I like to keep diff3
set, as it shows me what was there before I-and-they both changed the file in conflicting ways.)
When you run git checkout
without either naming a specific commit, or using the --ours
or --theirs
option, Git tries to get the version from the index. (Remember, the index—also called the staging area and sometimes the cache—is where you are building the next commit you will make.) But a conflicted merge leaves three versions of each conflicted file in the index. Git doesn't know which one to get, so it fails with that error. Using --ours
tells git checkout
to copy the "ours" (i.e., HEAD) version of the file from the index to the work-tree; using --theirs
tells git checkout
to copy the "other" (i.e., MERGE_HEAD) version of the file.3
When you do extract one of these version from the index, that leaves the other two versions in the index, i.e., leaves the file in unresolved-merge state. Inspect the contents carefully to be sure you have the correct version, then git add
the file to resolve the conflict. This will wipe out the three separate index versions, putting the work-tree version into the "resolved" index slot (slot zero).
If you need to re-create the merge conflict, you can use git checkout -m -- path
(the --
is only required if the path
resembles an option, but it is a good habit to get into). This works up until you run git commit
to finish the failing merge.
Once everything is resolved the way you want, use git commit
to finish the merge.
1You said git stash pop
, but git stash pop
is just a shortcut meaning "Run git stash apply
and then, if and only if that succeeds, run git stash drop
." Since the apply step failed, you will have to run git stash drop
manually, once you are satisfied that the stash has applied cleanly and been committed.
2I recommend avoiding git pull
. All it does is run two other Git commands for you: git fetch
, then either git merge
or git rebase
depending on what you tell Git in advance. It's better to run the two commands separately, so that:
git fetch
fetched.There's nothing fundamentally wrong with using git pull
, just remember that it's really git fetch && git something
, and you have to decide the "something" part ahead of time. If you don't pick one, Git will pick git merge
, which is probably the wrong default, but is what Git first did, way back in 2005, and therefore cannot be changed. :-)
3There is no --base
option, but you can use gitrevisions
syntax to access it from the index: git checkout -- :1:path
. You can use this same syntax to get at the --ours
version, which is index entry #2, and the --theirs
version, which is #3, but it's easier to remember --ours
and --theirs
anyway.
The "ours" version is sometimes called the local version, and the "theirs" version is sometimes called the remote version, but I hate these names. "Remote" in particular is much too easy to confuse with remotes like origin
and remote-tracking branch names like origin/master
.