Malloc
Malloc

Reputation: 16296

git pull doesn't actually restore my missing files from remote

I have been working on a branch. I committed and pushed it up to the remote repository. Now some files on that branch are missing. Hopefully they are still available on the remote branch, so I tried to do git pull:

git pull origin feature/my_branch

However, git said all is synchronized with remote:

 * branch            feature/my_branch -> FETCH_HEAD
Already up-to-date.

How can that be up to date? I cannot find my missing files locally, and my project didn't compile because of those missing files. Again, I can see those files in the commit history of the remote branch on bitbucket.

Upvotes: 35

Views: 39119

Answers (2)

Daniel Gomes
Daniel Gomes

Reputation: 629

git pull corresponds to the sequence of a git fetch and then git merge. So if you delete the files from your local repository, doing a git pull will not restore them.

In order to restore them you need to checkout that files from the remote repository using:

git checkout <branch name> -- <path/to/file>

<branch name> can be local or remote.

Example: Using remote repository

  1. Remote upstream name: origin
  2. Remote branch: feature/xpto
  3. Local branch: feature/xpto
  4. File missing on local branch: example.js
  5. Recover the file to the local branch from remote branch: git checkout origin/feature/xpto -- example.js
  6. Now you have example.js back on your local branch

Example 2: Rollback a commit

  1. git log
  2. Current commit hash 7bb2154cf23b68feb0a0bbbd95446f2cd8bf3a44
  3. Want to rollback to this commit hash dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad
    • git checkout dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad
  4. Only want to recover the file example.js from the above commit hash
    • git checkout dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad -- example.js

Upvotes: 38

torek
torek

Reputation: 489928

Assuming you've described the problem correctly, @danielcsgomes's methods should work fine.

You can find out which files are in your current commit, but not in your working directory, by running git status. For instance (using -s to keep the output short):

$ rm structy.py
$ git status -s
 D structy.py

To get just that one file back:

$ git checkout -- structy.py

and it's back.

Sometimes simply checking out some other branch or revision, then going back to where you were, will do the trick. For instance, the most recent commit on master here was to add mp.py, so if I do this:

$ rm mp.py
$ git status -s
 D mp.py
$ git checkout HEAD^
Note: checking out 'HEAD^'.
[verbiage about detached HEAD etc, snipped]
$ git checkout master
Previous HEAD position was 171ce6f... ignore *.log files
Switched to branch 'master'
$ git status -s
$ head -1 mp.py
from multiprocessing import Process, Queue

But this does not always work. It works for mp.py because the previous rev (HEAD^) doesn't have it, and the current one (master) does, so moving forward from HEAD^ to master restores the file. The file structy.py has been around for quite a while though, so if I remove it and check out HEAD^ or some other branch or whatever, it remains deleted-from-work-dir. So something like git checkout -- structy.py is an easier way to restore it, unless you want to go for the Very Big Hammer: git reset --hard.

If you're sure you want to abandon any changes you've made, you can git reset --hard HEAD. For instance, consider:

$ git rm mp.py
rm 'mp.py'
$ git status -s
D  mp.py

(by the way, note that the "D" is in a different position here: I "git rm"ed, not just "rm"ed, so I'm telling git that if I do a commit, mp.py should be removed in the new commit, it's not just an accident that I removed it). Then I decide, no, this is wrong, I want everything back to the way it was in HEAD:

$ git reset --hard HEAD
HEAD is now at 523bacb add multiprocessing example
$ git status -s
$ 

So, only use reset --hard if you're quite sure.

Upvotes: 8

Related Questions