MVCE would help
It would help if you showed, step by step, exactly what you did, or—even better—provided a minimal, complete, verifiable example (also known as an MVCE). Of course, the point of your question is that you don't know quite how you did this in the first place. But the thing is, we don't either! We can only guess.
My guess is that you never git add
ed the file in the first place. Let's look at my MVCE. I start by making a one-commit repository with a master
branch, with just a README file. (These commit messages are terrible, by the way.)
$ mkdir tt; cd tt
$ git init
Initialized empty Git repository in ...
$ echo demo failure to save file in stash > README
$ git add README
$ git commit -m initial
[master (root-commit) 0442487] initial
1 file changed, 1 insertion(+)
create mode 100644 README
Now let's make your co-worker's branch, which you would eventually bring into your repository as origin/master
. We can't make a remote-tracking branch this way (I could do it by cheating) so let's just use a regular branch:
$ git checkout -b other
Switched to a new branch 'other'
$ echo new file X > X
$ git add X
$ git commit -m 'new file X on branch other'
[other 37681f5] new file X on branch other
1 file changed, 1 insertion(+)
create mode 100644 X
$ git checkout master
Switched to branch 'master'
Now we are ready to go back to you being yourself. Let's make a new file and fail to git add
it. Let's also modify README
: we'll need this to make git stash
do anything. We can git add
the README
change, or not git add
it, whichever we prefer; this part will make no difference.
$ echo our new file X is different from his > X
$ echo 'add extra line to readme' >> README
You now ran git pull
and got a complaint. We literally can't run git pull
here, but we don't have to: all git pull
does is run git fetch
to get commits from your upstream remote, and then run git merge
to merge those commits into your current branch. I always recommend that those new to Git avoid git pull
: it's full of traps for the unwary, and you will have more problems than if you just use the two separate commands yourself.
So, we'll do the two-separate-commands thing. But: we do not (we can not) git fetch
your wo-worker's commit in this example, which is why we made a branch named other
above in the first place. So we just go right to the second command, git merge
:
$ git merge other
Updating 0442487..37681f5
error: The following untracked working tree files would be overwritten by merge:
X
Please move or remove them before you merge.
Aborting
(Note, by the way, that when you run git pull
, it effectively runs git merge origin/master
, rather than git merge other
. We are using other
here because we made this, rather than getting it through git fetch
.)
What stash does, and doesn't do
We have now reached the stage at which you ran git stash
. Had you run git status
first, you would have seen this, which might have been a clue, though it's hard to know at first what parts of this deserve what amounts of attention:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
Untracked files:
(use "git add <file>..." to include in what will be committed)
X
no changes added to commit (use "git add" and/or "git commit -a")
The two interesting bits of information here are that we have a modified, but not yet staged, README
, and—this is more important for our git stash
step—the untracked file X
.
Anyway, let's run git stash
(which means git stash save
) now:
$ git stash
Saved working directory and index state WIP on master: 0442487 initial
HEAD is now at 0442487 initial
Let's take a look at git status
now (I am guessing you did not—this is a mistake; you should check git status
frequently):
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
X
nothing added to commit but untracked files present (use "git add" to track)
There's that pesky X
still! The point here is that git stash save
doesn't save untracked files by default. (You can get it to do so, but if you had, that would have been even worse. Don't do this until you truly understand merging and merge issues: you'll get yourself into a huge trap that can only be resolved by understanding merge issues. This is yet another reason to avoid git pull
: if you learn to use git merge
directly, you will be on your way to understanding merges and the occasional problem.)
Now let's simulate git pull
again. Once again we must skip the fetch step and go straight to git merge
:
$ git merge other
Updating 0442487..37681f5
error: The following untracked working tree files would be overwritten by merge:
X
Please move or remove them before you merge.
Aborting
And here we have it: git stash
failed to help.
Let's try undoing the existing stash (which will put README
back into the modified-but-not-added mode) and then git add X
. Normally I recommend using git stash apply
first, checking the result carefully, and then using git stash drop
only if you are happy with that result, but we'll just run git stash pop
, which means git stash apply && git stash drop
:
$ git stash pop
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
Untracked files:
(use "git add <file>..." to include in what will be committed)
X
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1e7d19ea701fcc3dd8e0157c9a8a8555f74316a4)
Enough about git stash
! Let's go on to normal commits and merging...
Now we'll git add
the two files and commit, rather than stashing:
$ git add README X
$ git commit -m 'created file X'
[master 699e149] created file X
2 files changed, 2 insertions(+)
create mode 100644 X
Now we can merge. (Or, we could fetch-and-merge, via pull
, if we had a remote. But there's nothing new to fetch, and we don't have a remote. And besides, it's time to learn how merges work! So let's just merge.) We will get an add/add conflict:
$ git merge other
Auto-merging X
CONFLICT (add/add): Merge conflict in X
Automatic merge failed; fix conflicts and then commit the result.
Again, in your own case, you would be doing git merge origin/master
—or just plain git merge
, which uses your current branch's upstream setting, which is presumably origin/master
. But one way or another, we now have this "add/add conflict".
Resolving conflicts
When Git stops a merge with a conflict, it means Git doesn't know what to do. You must help it out here. You can run git status
to see how far Git got:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both added: X
no changes added to commit (use "git add" and/or "git commit -a")
Git has left, in our work-tree, the file X
. But there are two files named X
: ours, and your co-workers (which we're simulating as other
). Which one did Git leave us? Here's what is in X:
$ cat X
<<<<<<< HEAD
our new file X is different from his
||||||| merged common ancestors
=======
new file X
>>>>>>> other
So, the answer is that it left both versions of X
in the work-tree. (I have merge.conflictStyle
set to diff3
so mine shows "merged common ancestors" here. If you have the default merge.conflictStyle
setting, Git won't show that part. Since there are no common ancestors, that part is empty anyway—it's not really useful here. It's only useful when there are common ancestors, during a modify/modify conflict.)
It's now your job to come up with a merged version of X
, or perhaps separate out the two versions into two different files. Precisely what you want, and how you want to do it, is up to you. Let's say we'd like to rename our X
to something else, and extract their (your co-worker's) X
intact:
$ git show HEAD:X > X.ours
$ git checkout --theirs X
$ cat X.ours
our new file X is different from his
$ cat X
new file X
Now git status
will show the new untracked file X.ours
, as well as the conflicted file. Let's git add
both the adjusted X
(back to his version only) and the new X.ours
:
$ git add X.ours X
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: X
new file: X.ours
Since we're now ready to commit, we can conclude the merge now with git commit
.
(This is an example of correctly resolving the add/add conflict. I note that you say that this is not what happened; but I don't know what you did do, and without more information, I can't even guess what that was. I've been concentrating, above, on what git stash
can't do: it cannot help with add/add conflicts, and it does not save untracked files by default.)