When I run git show HEAD^:file.txt
git displays the content of this file at revision HEAD^
.
But when I run this command with the absolute path, i.e.: git show HEAD^:/home/me/repo/file.txt
it fails (exit code 128) with the message
fatal: path '/home/me/repo/file.txt' exists on disk, but not in 'HEAD^'
What would be an elegant way to show my file at revision HEAD^ when all my script has is the full path?
More details:
git show
command to work in a script. All I know is that the current working directory (from which the script is invoked) is in the git repo, but I don't have more clues about the layout of this repogit diff -- /home/me/repo/file.txt
behaves correctly)You can use git rev-parse --show-toplevel
to find the path to the worktree of any repo, then compute the path of your file relative to this worktree directory.
filepath=$1
worktree=$(git rev-parse --show-toplevel)
relpath=$(realpath -s --relative-to="$worktree" "$filepath")
git show -C "$worktree" HEAD^:"$relpath"
If you want to do this with any revision (not just HEAD^
), you should either have your script take the revision and the file path as 2 separate arguments, or split the unique argument revision:filepath
in 2 parts yourself.
One element about why <HEAD>:<abspath>
doesn't work as you expect:
<revision>:<path>
is a pretty low level notation to point at anything under a tree. If you feed it to git rev-parse
or git cat-file
for example, you will see the hash/type/content of the blob or subtree that is pointed to:
$ git rev-parse HEAD:path/to/file
7bb43a8cc90a1accbb6a167f9ed7c62af3f15b92
$ git cat-file -t HEAD:path/to/file
blob
$ git cat-file -p HEAD:path/to/file
-- ... content ... --
It is actually not restricted to commits, <revision>
can also be any tree :
$ git rev-parse HEAD:path/to
eacf32b...
$ git rev-parse eacf32b:file.txt
7bb43a8c..
Converting the string <revision>:<path>
into the id of a git object is one of the first action that is taken (it is not specific to the git show
command for example).
And this action is implemented by just looking at paths that exist within the git database.