Extract a Git Blob into a Temporary File
git unpack-file pulls a single blob out of Git's database and drops it in your current directory as an ordinary file. Read it with grep, less or anything else; the repository, index and working tree stay untouched throughout. Allow about ten minutes. You need Git 2.43.0 or compatible, and a local repository containing the blob you want to look at.
The route
Jump straight to the step you need, or tick off Done means at the end.
This follows the installed git-unpack-file(1) manual shipped by git-man version 1:2.43.0-1ubuntu7.3. The command has a deliberately tiny interface: give it one blob ID, it prints the name of the file it created.
1. Confirm the Git version and repository
Start with read-only checks. Skip sudo here: elevated privileges just leave the extracted file owned by root in a directory you cannot easily tidy up.
$ git --version
git version 2.43.0
$ git rev-parse --show-toplevel
/path/to/your/repository
Run these from inside the repository that holds the object. If the second command fails, change into a working tree or set GIT_DIR for a bare repository before continuing.
Checkpoint
A Git repository is selected and your version is visible. This is a low-level object operation, not a way to automatically restore a named file.
2. Resolve a path to its blob ID
The argument has to identify a blob, not a commit, tree or tag. A revision followed by a colon is the easy way to resolve a file out of a commit. Replace COMMIT and path/to/file with values that actually exist in your repository:
$ COMMIT=HEAD
$ PATH_IN_COMMIT='path/to/file'
$ blob=$(git rev-parse "$COMMIT:$PATH_IN_COMMIT")
$ printf 'blob: %s\n' "$blob"
blob: 0123456789abcdef0123456789abcdef01234567
$ git cat-file -t "$blob"
blob
- That object ID is a shape, not a value to paste. Repositories can use different object formats, so use the full ID your own command printed.
- Path not found? Check the spelling and the commit;
git rev-parsewill say the path does not exist. git cat-file -tnot printingblob? Stop.git unpack-fileis not built for that object type.
This step only resolves metadata. Nothing is checked out, the index is not touched, and nothing is written to the working tree.
3. Extract the blob
Pass the verified object ID as one quoted argument. Capture the command's standard output, because that output is the new file's name:
$ temporary_file=$(git unpack-file "$blob")
$ printf 'temporary file: %s\n' "$temporary_file"
temporary file: .merge_file_GB4wTq
The suffix is generated fresh every run, so expect a different one each time; the documented format is .merge_file_<random-suffix>. The file lands in your current directory, not beside the original path, and its contents are the blob's contents with no path or commit metadata attached.
Do not redirect this command's output to another file unless you specifically want a second copy: the useful result is the printed pathname, not anything on stdout to capture twice. Keep the variable alive in the same shell session while you inspect the result.
Checkpoint
A pathname beginning with .merge_file_ was printed and the file exists. If the command says it cannot read the object, re-check the repository, object ID and object type: a guessed hash is not a useful diagnostic.
4. Inspect and compare the contents
Use read-only tools to check the extraction. First confirm the file exists, then look at it, then compare it with the source path in the selected commit:
$ test -f "$temporary_file" && echo 'temporary file exists'
temporary file exists
$ sed -n '1,20p' "$temporary_file"
first line from the blob
more content from the blob
$ git show "$COMMIT:$PATH_IN_COMMIT" | cmp -s - "$temporary_file"
$ printf 'comparison status: %s\n' "$?"
comparison status: 0
Comparison status 0 means the extracted bytes match the selected commit's file exactly. The sed output above is only illustrative: do not treat a binary blob as text. For anything binary or large, reach for file, cmp or a checksum instead of printing it:
$ file "$temporary_file"
$ sha256sum "$temporary_file"
A successful extraction is not a checkout. Git has not touched the working-tree copy, and edits you make to the temporary file are never recorded as Git changes.
5. Remove the temporary file when finished
git unpack-file creates a file for you; it does not clean up after itself. Once you have finished with it, remove exactly the pathname held in the variable:
$ rm -- "$temporary_file"
$ test ! -e "$temporary_file" && echo 'temporary file removed'
temporary file removed
Warning
rm is irreversible. Check the variable with printf '%s\n' "$temporary_file" before you run it, especially if that variable came from an untrusted script. Need the data later? Copy it to a deliberately named destination and check that copy first, before removing the temporary file.
Shell session already gone before you cleaned up? Look only in the repository directory you used, and inspect candidate names before deleting anything. Never fire a broad wildcard such as rm .merge_file_* in a shared working directory: another process may own one of those files.
6. Diagnose the common mistakes
- A commit ID is not a blob ID. Passing
HEADstraight in asks Git to unpack a commit, and it fails because the command demands a blob. Resolve a file first withgit rev-parse COMMIT:pathand verify it withgit cat-file -t. - Working-tree files are not commit files. A path that exists in your working tree may not exist in the commit you picked. The colon expression reads the tree stored in that commit, so an uncommitted file cannot be resolved from
HEAD. For something staged in the index, use the appropriate index-aware lookup first. .merge_file_names are temporary artefacts, not restored working-tree paths. Rename or copy the result only after checking what it actually contains. No service restart, repository repair or elevated privilege is ever needed for this workflow.
Done means
- You confirmed the installed Git version and selected the correct repository.
- You resolved a real file to an object whose type is
blob. git unpack-filereturned a generated pathname in the form.merge_file_<random-suffix>.- You verified the extracted contents without changing the repository.
- You removed the temporary file, or deliberately kept a checked copy under a clear name.