Consider only files being pushed in pre-push hook git

Viewed 110

I want to run lint on code for pre-push without considering the local changed files the user has. for example change in file A is being pushed and the same got changed in the local changes I want to consider the code being pushed by user.

How to implement this using hit-hooks.

Alternate ways I tried: Limiting the user to reset the changes in pre-push - The functionality is limited in this case

1 Answers

There are several ways to get files from git storage and write them to disk, but I don't know of a direct command to say straight away "checkout files A, B and C from commit xxx to that directory on disk".


The simplest way is probably to use git worktree add (but this checks out all files, not just the ones you want) :

git worktree add /tmp/myhook.xyz <commit-sha>

The most direct way is to use git --work-tree=... (or GIT_WORK_TREE=...) to target some other directory on disk :

git --work-tree=/tmp/myhook.xyz checkout <commit-sha> -- file1 file2 path/to/file3

How to use this in a pre-push hook:

for each pushed reference, you can :

  • compare the local commit and remote commit to list files that were modified,
  • use the above trick to checkout the files from local commit in a specific destination on disk :
# pre-push:
#!/bin/bash

zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')


list_modified_files () {
        local $local_commit=$1
        local $remote_commit=$2

        if [ "$local_commit" = "$zero" ]; then
                return
        fi

        if [ "$remote_oid" = "$zero" ]; then
                git ls-tree -r --name-only $local_oid
        else
                git diff --no-renames --diff-filter=AM --name-status $remote_oid $local_oid
        fi
}



while read local_ref local_oid remote_ref remote_oid
do
        echo "'$local_ref' '$local_oid' '$remote_ref' '$remote_oid'"
        tmpdir=$(mktemp -d /tmp/myprepushhook.XXXXXX)
        list_modified_files | xargs -r git --work-tree "$tmpdir" checkout "$local_oid" --

        # run linter on files in $tmpdir ...

        rm -rf "$tmpdir"
done
Related