1

I have a repo in which a number of files are committed.

I checked out an older revision of a particular file (without making a branch).

In all git tutorials there are visual explanations with pictures such as

A  B  C  D
*--*--*--* <-- master <-- HEAD

describing how a particular file has changed.

Now check out B, giving Detached Head

A  B  C  D
*--*--*--* <-- master
   ^
    \-- HEAD

( Acknowledgement, ascii art taken from Brian Campbell post Checking out an old commit and maintaining the head on the master branch? )

I see that this is an accurate situation for the particular file. However, I believe the other files in the repo are still latest version, since an old revision of only one file was checked out.

The question: how can a single HEAD be valid for all the files in a folder, including some that are more recent than the commit referred to by the HEAD. Should there be one HEAD pointer per file?

In typing this question, I am now guessing that maybe the HEAD concept applies to the local (or remote) repo and has nothing to do with the working directory. So the fact that most of the files in the working directory are newer than HEAD is "just the way it works".

beginner
  • 43
  • 2

2 Answers2

1

When you do git checkout B -- path, you don't get into a detached head state, and your working tree isn't changed to the state of B. Only the specified path in the working tree is set to the state of B.

If on the other hand you do git checkout B, you get into detached head state, and the content of the entire working tree is set to the state of B.

janos
  • 120,954
  • 29
  • 226
  • 236
1

The diagrams you show do not describe the state of a file. They only can be used to describe the overall state of the repo.

Importantly, those diagrams don't show the index or the work tree. Only the state of the database is shown (commits and refs).

And checkout is one of those commands that can perform very different operations depending on the particular arguments. In particular, when you say you want to check out a specific path, the requested version gets copied to your work tree - but the other things checkout does when you don't specify a path, like updating HEAD, don't happen. The diagrams you've shown describe those things that, when a path is given, don't happen.

So if you are on master and you say

git checkout B some/file

then the diagram would still look like

A  B  C  D
*--*--*--* <-- master <-- HEAD

If you do a git status, you should see that you are still on master (not in detached HEAD state), and the file you checked out should show up as modified.

This is part of a broader fact about git: each commit is a snapshot of the entire project. (So is the index. So is the work tree.) Some very old source control systems (like cvs) keep independent histories of each file, but not so in git. So you can copy a file from an older version to your index and work tree, where it will be treated as an uncommitted change; but you can't really put the repository in a state where "different versions of different files are checked out".

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52