Subject: Re: Why does git checkout -b touch the index?

From: Junio C Hamano <[email-masked]>
Date: Fri, 14 Oct 2016 09:07:55 -0700

David Turner <[email-masked]> writes:

> If I do "git checkout -b fleem", with no additional flags, why does it
> need to rewrite the index?  Or even read the index? 

The "reading" part can be explained easily.

It needs to show the list of dirty paths, which involves reading the
index, refreshing them in-core to cull the timestamp-only changes
out of the report.  

Once in-core index is refreshed, it is a waste not to write them out
if it can, so it is not surprising if it writes, too.

The real reason is a lot more involved.  "git checkout -b new" is
different from "git update-ref refs/heads/new HEAD" (i.e. create a
new branch at the same commit) followed by "git symbolic-ref HEAD
refs/heads/new" (i.e. point the HEAD at it).  If it were, I fully
agree with you that it shouldn't need to touch either index or
working tree at all.

It is "git branch new" followed by "git checkout new", and the
latter step does the full two-tree "read-tree" between the same two
commits.  I personally very much prefer "Switching between the same
two commits?  That should be a no-op by definition.", but we cannot
blindly that naive optimization, as it would break some use cases
(which I personally do not care too much about ;-).

For example, extra working tree files outside the "sparse" area are
removed when sparse-checkout is in use while switching from the
current branch to the new and identical branch.  I do not personally
agree with the behaviour, but that has been what the users accept;
there may be other funnies like that.