Home / Alt manpages / git-checkout-index(1)

  • git-checkout-index(1)
  • User command
  • linux

Restore Tracked Files Safely with git checkout-index

You will finish with a practical way to copy tracked files from Git's index into the working tree, including a controlled export of the whole index. The examples use Git 2.43.0, supplied here by git-man version 1:2.43.0-1ubuntu7.3.

Allow about ten minutes. You need an existing Git working tree with committed or staged content. These commands do not need elevated privileges. They can overwrite local files, so inspect the target paths first and keep a recoverable copy of anything you have not committed.

Checkpoint: understand what will change

git checkout-index reads the index, sometimes called the staging area. It copies the cached version of each selected path into the working directory. By default it does not overwrite a file that is already there. It does not fetch from a remote and it does not update the index unless you ask for its stat information to be refreshed.

Check the repository and the paths before doing anything destructive:

$ git status --short
$ git ls-files --error-unmatch path/to/file

The first command shows local changes. The second confirms that the path is tracked in the index. Replace path/to/file with a real path; the command exits non-zero when the path is not indexed.

1. Restore one tracked file without overwriting it

Give the path after --. This makes it clear that the remaining argument is a filename, even if it begins with a hyphen:

$ git checkout-index -- path/to/file

If the working-tree file is absent, its indexed contents are created. If it already exists, Git leaves it alone and may report that it will not overwrite it. That default is the useful safety boundary. A command with no path does nothing, so do not assume that bare git checkout-index restores everything.

Checkpoint: compare the restored file with the index version:

$ git diff -- path/to/file
$ git diff --cached -- path/to/file

The first comparison is against the index and should be empty if the working file now matches it. The second compares the index with HEAD; it tells you whether the cached version itself is staged content rather than the last commit.

2. Force an overwrite only after checking the path

-f or --force replaces an existing working-tree file with its indexed contents:

$ git diff -- path/to/file
$ git checkout-index -f -- path/to/file
$ git diff -- path/to/file

Warning: the force command changes the file immediately. Any uncommitted working-tree content in that path is lost. The index and HEAD do not provide an automatic undo for content that existed only in the working tree.

If you forced the wrong file, recovery depends on where the lost content still exists. Check an editor backup, filesystem snapshot, separate copy, or a commit. If the content was staged before the overwrite, git checkout-index -f -- path/to/file can restore that staged version again. Otherwise stop writing to the affected filesystem and use your normal recovery process.

3. Restore the complete index

Use -a or --all when the target is every ordinary entry in the index:

$ git checkout-index -a

This creates missing files but still does not overwrite existing ones. To refresh every path from the index, combine it with -f:

$ git checkout-index -f -a

That combination is broad and destructive to uncommitted working-tree edits. Review git status --short first. If you only want files that already exist, add -n or --no-create; it refreshes existing paths and does not create new ones:

$ git checkout-index -n -f -a

The index can mark paths with the skip-worktree bit. Ordinary -a respects that bit. Add --ignore-skip-worktree-bits only when you deliberately want those paths included:

$ git checkout-index -f -a --ignore-skip-worktree-bits

4. Export the index into another directory

The prefix option is useful for producing a tree of files without changing the repository's normal working paths. The destination must already exist, and the prefix should normally end in a slash:

$ mkdir -p ../exported-tree
$ git checkout-index --prefix=../exported-tree/ -a

Git writes each indexed path below that prefix. For example, src/main.c becomes ../exported-tree/src/main.c. The trailing slash matters because the prefix is literal text: --prefix=../exported-tree would produce a name such as ../exported-treesrc/main.c.

Existing files below the destination are protected by the normal no-overwrite rule. If you intend to replace an earlier export, inspect it first and use -f only after confirming that the destination is disposable. This operation does not need root and does not alter the index.

5. Feed paths from another command

For a generated list, use --stdin rather than putting every path into one shell command:

$ find . -name '*.h' -print0 | git checkout-index -f -z --stdin

-z changes the separator to a NUL byte, so filenames containing spaces, quotes or newlines are passed as complete paths. The -- marker is not used here because --stdin supplies the paths. The force flag still makes this destructive: the command replaces matching working-tree files with their indexed copies.

For a small, known list, a quoted shell list is easier to review:

$ printf '%s\0' 'docs/one.h' 'src/two.h' | git checkout-index -z --stdin

Without -z, standard input uses one path per line. Prefer NUL separation whenever another program is producing the list.

6. Handle merge stages or temporary output

An unresolved merge can leave multiple index stages for a path. --stage=1, --stage=2 or --stage=3 selects one stage, provided the requested number is between 1 and 3:

$ git checkout-index --stage=2 -- path/to/conflicted-file

Use this when an external tool needs one particular side of an unmerged entry. Do not guess which stage is correct; inspect the merge context and the tool's documentation first.

--temp writes each selected entry to a temporary file instead of the working tree and prints a tab-separated association:

$ git checkout-index --temp -- path/to/file
.merge_file_XYZ123	path/to/file

The temporary filename is relative to the repository's top level. The path shown is the tracked path relative to the current directory. With --stage=all, Git implies --temp and prints three temporary names, one for each available stage, followed by the path. A dot means that stage is absent.

Temporary files are for the consuming tool to process. They are not a persistent restore point, and the command does not update index stat information in this mode.

Done means

  • You confirmed the target paths with git status or git ls-files.
  • You used a specific path or -a deliberately; bare git checkout-index did nothing.
  • You used -f only after accepting that uncommitted file content could be lost.
  • You verified the result with git diff -- path/to/file or inspected the export.
  • You used --stdin -z for generated filenames that may contain whitespace or newlines.