I seem to have lost my afternoon's work in a new repo. Here's what I did:
git init
git add src
git remote add origin [email protected]:Synesso/memx.git
git pull origin master
git add .gitignore
git commit -m 'updated ignore'
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.
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.
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.
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.
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.
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
? :-)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With