thyme thyme - 18 days ago 5
Git Question

git checkout deletes files

I am new to git and I wanted to try the branch feature. I am working with a local repository. The problem is that if I create a new branch and then go back to the master branch, some files are lost.

This is what I do:

I have two directories:

$ ls
g_LT LT


and a source code file lt_mp2.F in the LT directory:

$ ls LT/ | grep lt_mp2.F
lt_mp2.F


The other directory contains a relative symlink to this file:

$ ls -l g_LT/ | grep lt_mp2.F
lt_mp2.F -> ../LT/lt_mp2.F


Both files are lost if I create a new branch and then go back to the master branch. So, let me show this:

Before I create the new branch, let's check that there is nothing to commit:

$ git status
HEAD detached from 2617e8a
nothing to commit, working directory clean here


Let's also check that we are in the master branch and that the last commit is from Oct 13 2016

$ git branch -a
* (detached from 2617e8a)
master

$ git log
commit 3484261bdd585671bf7c74568542a62610c2deaf
Author: [...]
Date: Thu Oct 13 09:25:06 2016 +0200
[...]


Now I create a new branch:

$ git checkout -b testbranch
Switched to a new branch 'testbranch'


The source files are still there:

$ ls LT/ | grep lt_mp2.F
lt_mp2.F
$ ls -l g_LT/ | grep lt_mp2.F
lt_mp2.F -> ../LT/lt_mp2.F


Now I go back to the master branch:

$ git checkout master
Switched to branch 'master'


But now the source files are gone:

$ ls LT/ | grep lt_mp2.F
(no output)
$ ls -l g_LT/ | grep lt_mp2.F
(no output)


Moreover the last commit is suddenly from Dec 2015 instead of Oct 13 2016:

$ git log
commit 634741172ed34cd687fd91f14da45004b3328f8b
Author: [...]
Date: Tue Dec 1 18:54:57 2015 +0100
[...]


What is happening here and why am I losing my source files?

Answer

You're not (losing any files, nor any commits).

This part of your starting claim is wrong:

Let's also check that we are in the master branch [snip]

$ git branch -a
* (detached from 2617e8a)
master

This shows that you are not on branch master at the start. Instead, you have a "detached HEAD". The most recent explicit git checkout of a raw hash ID, or equivalent—such as a tag name, or a remote-tracking branch name—checked out commit 2617e8a. Your git log output shows that the current commit is probably1 3484261bdd585671bf7c74568542a62610c2deaf, and the "detached from" wording suggests that you probably made this commit yourself (Git uses "detached at" when you have not moved HEAD, and "detached from" when you have).

The git log command defaults to showing commits starting from your current (HEAD) commit2 and working backwards. This is true whether HEAD is "detached" or not. (A non-detached HEAD is a HEAD that refers to a branch name, such as master. Running git checkout branchname gives you a non-detached HEAD, i.e., HEAD now points to branchname, so that commits are found using the named branch.)

If you want to see more or other commits, you can tell git log to start somewhere else. Wherever you tell it to start, it works backwards from there.

Thus, this just means that master, the branch name, points to a commit from back in 2015. Once HEAD points to master, git log (with no additional arguments) starts with its most recent commit and works backwards from there.

Presumably if master is that out of date, all the real work has been happening on some other branch(es).

The files disappear when you switch from 3484261... to 6347411... (this is probably the commit identified by master) because they are in the former commit and are not in the latter. So Git removes them from the index and work-tree when switching commits. Switching back to 3484261... (by checking it out by ID, or by the new name you gave it) will put them back into the index and work-tree.


1git log sorts its output by date, by default, showing commits with later dates first. This code changed somewhat at some point that I missed, because it used to be possible to "post-date" a commit into 2038 or so, so that it was always shown at the top of git log output, if it was to be shown at all. This had stopped working when I tested it recently.

2See footnote 1, and note that you can change the sort order, and/or constrain it, e.g., with --topo-order. Adding --graph sets --topo-order. Usually, commits' dates are more or less in line with their graph topology, so that these flags do not make huge changes in sorting order.

Comments