Arkadiy Arkadiy - 2 months ago 14
Git Question

What exactly does "git update-index -g" with no other options do?

I've been looking at man page for

git update-index
. I simply do not understand what it does when
-g
is passed. That option selects files already in index that are different from HEAD. But what is done to those files?

A lot of discussion on the Net is about
--assume-unchanged
, but I'd like to understand the basic functionality.

P.S.: I think I do understand what index does, how
git add
and
git reset
works.

Kaz Kaz
Answer

From my reading of the manual page, it does nothing. Because:

   Modifies the index or directory cache. Each file mentioned is updated
   into the index and any unmerged or needs updating state is cleared.

"Each file" is the empty set if there are no file arguments, and I can't find anywhere that special semantics is assigned to the empty case.

However, git update-index does check whether it is in a Git repo:

~$ git update-index
fatal: Not a git repository (or any of the parent directories): .git
~$ echo $?
128

Thus, git update-index with no arguments at least performs a sanity check and provides an error message and termination status. If it really does nothing otherwise, it could be used in scripts for checking whether they are in a git repo. Mind you, so could other commands like git rev-parse with no arguments.

If by "no arguments" you mean "no options, but with file arguments present", then what it does is perform the action on those of the specified files which are already in git. When it encounters a file argument which is an untracked file, it gives an error diagnostic, because --add was not specified. It exits with a failed termination status and the index is unmodified.

So basically with no options it provides a sanity check: either it is able to operate on all of the specified files, or else it bails and does nothing. This prevents the situation when the intent is only to operate on tracked files.

The purpose of -g/--again is to provide a way of repeating git update-index on those files that have already been staged, with modifications. What it does with those files is update them again, so that the index matches the working copy.

You can have a situation in which a given file is different in the HEAD commit, staged index, and working copy. This happens when you hack on the file, and then stage it with git add (or git update-index), at which point the index is the same as the working copy; and then you hack on it again. Now it is different from the index, and that is different from HEAD. By updating it to the index again, you sync the index with the working copy, so the only thing different is HEAD.

Note that when you do a git diff, you compare the working file to the index. To see the index-to-HEAD difference, do git diff --cached, and working-to-head use git diff HEAD. Thus you hack on a file and then stage it, then hack on it again, git diff will show you just the latest hack between the staged and working. The original hack is git diff --cached, and the overall combined hack is git diff HEAD. Armed with this, you can explore what effect git update-index is having.

It seems that -g is useful with file arguments: git update-index -g file-j file-k means "do update-index on all the stuff that has staged modifications and also do it on newly hacked file-j and file-k."