25

The questions I've seen for undoing a git pull a slightly different to mine.

This is what I've done:

There is a project in directory A (not a repo). I initialized a repository in it, added the files, but did not commit anything. Then I pulled from repository B, which overwrote a bunch of my staged files.

I was under the impression I could use git reset --hard to undo the merge. Of course that just checked out the HEAD of the commits I had just pulled in.

I should have branched and commited something before I did this pull, hindsight is nice. Is there some way I can get my old unstaged files back?

Benbob
  • 13,876
  • 18
  • 79
  • 114
  • 3
    One thing that could save you a bit of grief in the future is `git reset --merge`. Files that were unaffected by the merge get left alone, and since git will refuse to try to merge if you have modifications to files the merge will touch, it covers your bases pretty well! – Cascabel Jan 18 '11 at 07:37
  • Also, did a pull really overwrite staged files? That doesn't make sense to me. As I said in the previous comment, git will refuse to merge in cases like that. Was it maybe the `reset --hard` that blew them away? – Cascabel Jan 18 '11 at 07:43
  • Yes I think it was the `reset --hard`. It's a little like `rm -rf`, dangerous in the wrong hands. – Benbob Jan 18 '11 at 08:12
  • possible duplicate of [Recovering added file after doing git reset --hard HEAD^](http://stackoverflow.com/questions/1108853/recovering-added-file-after-doing-git-reset-hard-head) – poke Mar 01 '14 at 16:47

5 Answers5

31

A git pull is the same as git fetch + git merge. It is the merge step that overwrote your changes. To revert to the state before the merge, use git log to find your latest commit and then use git reset --hard 1234abcd where 1234abcd is the hash of the desired commit.

Note that after the reset git pull will merge the changes again. To revert the changes for good, use git revert which will create an additional commit reversing the changes.

Gintautas Miliauskas
  • 7,744
  • 4
  • 32
  • 34
  • 1
    This would normally work, but as stated in the question, he only staged the changes. There is no commit. Therefor nothing to reset too. – geoffreyd Jan 18 '11 at 00:06
  • The thing is I had no commits before the merge, just a stage. Pretty sure I just accidentally all my files. – Benbob Jan 18 '11 at 00:06
  • `ORIG_HEAD` is the state of `HEAD`, before a merge or other commands which may be dangerous. Unfortunately it won't help here, as the other commenters noted. – Mikael S Jan 18 '11 at 00:09
  • 1
    `git reset --hard` overwrites staged changes (so does `git reset`, but not `git reset --soft`). If the change was not committed, it was not saved. – Jay Conrod Jan 18 '11 at 00:09
  • Oh, you're right. I thought `merge` did not work on repositories with uncommitted changes. As for the data, I think staged files are recorded in git's internal data store, so it may still be possible to dig them out of there. – Gintautas Miliauskas Jan 18 '11 at 00:19
13

It seems there is an answer to recovering staged files here:

Recovering added file after doing git reset --hard HEAD^

Community
  • 1
  • 1
geoffreyd
  • 1,089
  • 6
  • 15
3

Either just reset to the previous HEAD (i.e. the commit you had in your repository, that wasn't updated from the remote), or use git reflog. The latter displays a list of actions that were made in your repository, the git pull command should be part of that. Simply git reset --hard X to a state before that command.

Or just branch off the previous HEAD (you may delete/overwrite the previous branch), do your changes there and git pull again...

poke
  • 369,085
  • 72
  • 557
  • 602
1

I think you cannot full recover now. The best you can do is git status to check which file(s) are still intact. If the uncommitted files are not here, they are lost.

Next time, consider using git stash before git pull, or, better yet, use git fetch.


IF YOU ARE A ADVANCED GIT USER, AND THE FILES ARE REALLY IMPORTANT:

If the files are staged, you may be able to extract them from the object repository. But these go right into git guts, which I don't think you should try.

If you really want, read these:

Community
  • 1
  • 1
J-16 SDiZ
  • 26,473
  • 4
  • 65
  • 84
  • Hadn't thought of stashing it. Branching seemed like the safer option anyway. Lesson learned, after I restored all the files from my IDEs history I initialized and commited, then ran `git-fetch` and then `git-merge`. Worked great. – Benbob Jan 18 '11 at 08:16
0

Update January 17, 2011, 6:53 PM

Just reread your question. I overlooked that you were pulling from project b as opposed to copying files into your project. Not sure if my answer still holds given your scenario. I think your best bet is to follow geoffreyd's answer and checkout the answer to the StackOverflow question Recovering added file after doing git reset --hard HEAD^.

Original Answer

Just do a git checkout -- <file>.

Here's the example I ran to confirm the above...

# Create a test directory and some test files
$ mkdir blah
$ echo "I've been overwritten" > test1.txt
$ cd blah
$ echo "I'm the real test1.txt" > test1.txt
$ git init .
Initialized empty Git repository in /Users/matthew/blah/.git/
$ git add .
$ cp ~/test1.txt .
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   test1.txt
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   test1.txt
#
$ cat test1.txt
I've been overwritten
$ git checkout -- test1.txt
$ cat test1.txt
I'm the real test1.txt

When you perform git status it tells you to use git checkout -- <file> to discard changes in the working directory. If I'm reading your question correctly, that's what you want to do.

Community
  • 1
  • 1
Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163