Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
756 views
in Technique[技术] by (71.8m points)

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

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 git@github.com: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 git@github.com: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 git@github.com: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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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? :-)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...