Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stage files, then remote add, then pull - and my files are gone

Tags:

git

github

I seem to have lost my afternoon's work in a new repo. Here's what I did:

  1. Created a new project locally and did some work.
  2. Created a repo on github
  3. git init
  4. git add src
  5. git remote add origin [email protected]:Synesso/memx.git
  6. git pull origin master
  7. git add .gitignore
  8. git commit -m 'updated ignore'
  9. git push origin master

Both my local repo and the github repo have only two commits. The initial commit (made by github on project creation) and a second one that includes only the file .gitignore.

The files added in step 4 (git add src) are not present. Nor do they appear to be staged.

Do you lose staged files when you do a git pull? Can I retrieve them somehow?

Current state:

$ git status
# On branch master
nothing to commit (working directory clean)

My inital add is not in the reflog.

$ git reflog
c80135d HEAD@{0}: checkout: moving from 999d128ea4e6969f9eacbceebb5f857f2aa5abb0 to master
999d128 HEAD@{1}: checkout: moving from master to HEAD~1
c80135d HEAD@{2}: checkout: moving from 999d128ea4e6969f9eacbceebb5f857f2aa5abb0 to master
999d128 HEAD@{3}: checkout: moving from master to 999d128ea4e6969f9eacbceebb5f857f2aa5abb0
c80135d HEAD@{4}: commit (amend): updated ignore
28b4f90 HEAD@{5}: commit: updated ignore
999d128 HEAD@{6}: initial pull

history shows that I added the src folder, but did not commit it:

223  git init
225  git add src
229  git add project/Build.scala
234  git remote add origin [email protected]:Synesso/memx.git
250  git pull origin master

I know git will complain if you try to pull with dirty files present. But it's OK with doing a pull that will obliterate staged files? That seems wrong.


I've just tested this process again and yes, it destroys staged files.

jem@jem-usb:~/projects$ mkdir x
jem@jem-usb:~/projects$ cd x
jem@jem-usb:~/projects/x$ git init
Initialized empty Git repository in /home/jem/projects/x/.git/
jem@jem-usb:~/projects/x$ echo "hi" > hello.world
jem@jem-usb:~/projects/x$ git add hello.world
jem@jem-usb:~/projects/x$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   hello.world
#
jem@jem-usb:~/projects/x$ ls -asl
total 24
 4 drwxrwxr-x 3 jem jem 4096 Apr 28 20:56 .
 4 drwxr-xr-x 8 jem jem 4096 Apr 28 20:56 ..
 4 drwxrwxr-x 7 jem jem 4096 Apr 28 20:56 .git
12 -rw-rw-r-- 1 jem jem    3 Apr 28 20:56 hello.world
jem@jem-usb:~/projects/x$ git remote add origin [email protected]:Synesso/memx.git
jem@jem-usb:~/projects/x$ git reflog
fatal: bad default revision 'HEAD'
jem@jem-usb:~/projects/x$ git pull origin master
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 7 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (7/7), done.
From github.com:Synesso/memx
 * branch            master     -> FETCH_HEAD
jem@jem-usb:~/projects/x$ ls -asl
total 36
 4 drwxrwxr-x 3 jem jem 4096 Apr 28 20:53 .
 4 drwxr-xr-x 8 jem jem 4096 Apr 28 20:52 ..
 4 drwxrwxr-x 8 jem jem 4096 Apr 28 20:53 .git
12 -rw-rw-r-- 1 jem jem   59 Apr 28 20:53 .gitignore
12 -rw-rw-r-- 1 jem jem    9 Apr 28 20:53 README.md
jem@jem-usb:~/projects/x$ git reflog
c80135d HEAD@{0}: initial pull

The file hello.world was deleted without warning.

like image 214
Synesso Avatar asked Apr 28 '12 09:04

Synesso


People also ask

How do I retrieve files from a remote repository?

The Git Pull Command The “remote” parameter refers to the remote repository you want to pull to your local machine. When you run this command, the remote repository will be retrieved then merged into your local copy of the repository. The git pull command does not affect untracked files.

Will git pull erase my changes?

Never pull before you commit any valid changes. This will wipe off all your changes. To retain your code, you have to commit, then pull, then finally push.

Does git pull remove local files?

Important: If you have any local changes, they will be lost. With or without --hard option, any local commits that haven't been pushed will be lost. If you have any files that are not tracked by Git (e.g. uploaded user content), these files will not be affected.

How do I find missing files in git?

Recovering Deleted Files with the Command Line Git provides ways to recover a deleted file at any point in this life cycle of changes. If you have not staged the deletion yet, simply run `git restore <filename>` and the file will be restored from the index.


2 Answers

I was able to reproduce this without using github, using two hosts (renamed here as hostB, which is the "remote", and hostA, which is the "local"):

hostB$ cd /tmp; mkdir repo; cd repo; git init
Initialized empty Git repository in /tmp/repo/.git/
hostB$ : > .gitignore; echo this is a readme > README.md
hostB$ git add .; git commit -m initial
[master (root-commit) 58d43bd] initial
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 README.md

hostA$ cd /tmp; mkdir repo; cd repo; git init
Initialized empty Git repository in /tmp/repo/.git/
hostA$ echo hi > hello.world
hostA$ git add hello.world
hostA$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   hello.world
#
hostA$ git remote add origin ssh://hostB.dom.ain/tmp/repo
hostA$ git pull origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From ssh://hostB.dom.ain/tmp/repo
 * branch            master     -> FETCH_HEAD
hostA$ ls
README.md

Important: you can use git fsck --lost-found to recover your staged files:

hostA$ git fsck --lost-found
Checking object directories: 100% (256/256), done.
dangling blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057
hostA$ 

and sure enough, if you examine the blob(s) (which are now restored in .git/lost-found/other), those will have your lost stuff. (Any directory structure will be gone though, and you'll have to figure out which file is which and re-put them where you want them.)

Interestingly, if you git fetch origin followed by git merge origin/master, it grabs the origin's initial revision(s) (with the .gitignore and README.md files from hostB, in this case) and retains your "changes to be committed". Another reason to favor git fetch followed by git merge? :-)

like image 200
torek Avatar answered Nov 15 '22 08:11

torek


I received the following reply on the git mailing list from Junio Hamano:


It is an unanticipated corner case interfering our attempt to be too nice that backfired.

For a long time, having no history and asking to pull was forbidden, because "git pull" is is about combining two (or more) histories together and pulling when you have no history is a nonsense --- you only have one history (the history from the other side) and there is nothing to combine.

Later we tried to be nicer, as some new users triggered an error when doing "git init" in an empty directory followed by "git pull", by redefining "merge" into no history to mean resetting to the other history.

This solved "git init && git pull", but we did not anticipate anybody would do a "git init && git add && git pull" sequence, to which there is no sane outcome other than just erroring out.

A patch to give that only sane outcome may look like this.

 git-pull.sh |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/git-pull.sh b/git-pull.sh
index 2a10047..da102d0 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -261,6 +261,9 @@ esac

 if test -z "$orig_head"
 then
+       test $(git ls-files | wc -l) = 0 ||
+       die "$(gettext "Uncommitted changes in the index")"
+
       git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
       git read-tree -m -u HEAD || exit 1
       exit
like image 23
Synesso Avatar answered Nov 15 '22 07:11

Synesso