Diomidis Spinellis
Diomidis Spinellis

Reputation: 19345

How can I efficiently see the contents of a renamed file maintained under git?

With the git command

git log --follow --pretty='format %H %ae %ai' foo.c

I get a list of changes that affected the file foo.c. Then, given a hash H from the git log output, I can run

git show H:foo.c

to see the file's contents at that point of time.

This doesn't work if the file has been renamed; git complains:

fatal: Path 'foo.c' exists on disk, but not in '34cd81d75f398ee455e61969b118639dacbfd7a6'.

What is the most efficient way obtain the renamed file's contents?

Upvotes: 2

Views: 55

Answers (1)

torek
torek

Reputation: 488183

EDIT: I just realized, you can add the --diff-filter=R to the git log --follow command. (I've edited this into the answer.) This cuts down the number of hashes to inspect, to just those that rename the file in question. However, one still must extract the file-rename separately.


Here's the above comment turned into a script ... no claims about how pretty it is or is not. :-) It needs more work to be turned into a real command.

#! /bin/sh

# Find git commits that rename the given path.
identify()
{
    local path="$1"
    local IFS=$'\t'

    # 1) log with follow to extract hashes that rename the file
    #
    # 2) diff-tree each hash to get the actual rename involved
    #
    # 3) extract the hash and :<...>R line with old/new paths
    git log --follow --pretty='format:%H' --diff-filter=R -- "$path" |
    while read hash; do
        echo $hash
        git diff-tree -M -r --diff-filter=R $hash
    done |
    while read line; do
        case "$line" in
        :*)
            set -- $line
            # $2 is oldname, $3 is new name
            # we already have the new name, we need to back
            # up to the old one.
            [ "$3" != "$path" ] && continue
            # at and before this commit, use $2, the old name
            echo at and before $hash use $2
            path=$2;;
        *)
            hash=$line;;
        esac
    done
}

identify builtin/var.c

Upvotes: 2

Related Questions