Optional githook behaving like optional

I'm trying to use this meaning in my workflow how post-merge

and post-checkout

git hooks.

#!/usr/bin/env bash
# MIT Β© Sindre Sorhus - sindresorhus.com

# git hook to run a command after `git pull` if a specified file was changed
# Run `chmod +x post-merge` to make it executable then put it into `.git/hooks/`.

changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"

check_run() {
    echo "$changed_files" | grep --quiet "$1" && eval "$2"
}

# Example usage
# In this example it used to run `npm install` if package.json changed
check_run package.json "npm install"

      

This means only run npm install if the file package.json

has changed.

However, on all machines I have tried this. The npm install command runs regardless of whether package.json has been modified or not.

To test this, I create a new branch on my current commit and then checkout it, thereby triggering a post-checkout

git hook . I didn't expect to npm install

be launched because it package.json

won't change.

Visual Proof (note the npm warning text):

enter image description here

+3


source to share


2 answers


TL; DR

Use another hook after checking which uses $1

instead ORIG_HEAD

. (Or, check the number of arguments to decide if you will be called as a post-checkout or a post-merge hook to get the same effect. Or, if you know reflogs are always on, use HEAD@{1}

to get the previous value HEAD

.)

Discussion

Using ORIG_HEAD

in a post-merge hook makes sense because it git merge

sets ORIG_HEAD

to the commit that was current before the merge. (If the merge was a true merge rather than fast forward, the commit identified MERGE_HEAD

and the commit identified with HEAD^1

are necessarily identical. However, if the merge was fast forward, then only the MERGE_HEAD

reflog will be able to find the previous hash that was stored in HEAD

before the merge. .)

ORIG_HEAD

Post-validation cache usage , however, is clearly flawed because it git checkout

doesn't install ORIG_HEAD

. This means that ORIG_HEAD

even if it exists at all, it actually indicates a random occurrence. (Of course, in fact it permits everything that has been recorded in it any, last updated command: git merge

, git rebase

or any other command that writes to ORIG_HEAD

. But the point here is that it does not have any relation to the fixing, which was current before discharge.) Quest after check :



three parameters are given: ref of the previous HEAD, a link to the new HEAD (which may or may not have changed), and a flag indicating whether the check was output checkout (changing branches, flag = 1) or checking a file (getting a file from an index, flag = 0). This hook cannot affect the git output.

(the last sentence is not entirely correct. Although the post-check hook cannot stop the check when the index and working tree are updated, it can overwrite various data in the working tree or index, and if it issues a crash status, it calls itself git checkout

to create a crash status .)

All this means that you need to perform another action in the cache after checking: use the $1

first parameter to get the hash id of the previous one HEAD

. Note that in exotic cases, the 1 on the initial git clone

starts the hook after the check, so there $1

may be null-ref. (I'm now curious what it is when you use git checkout --orphan

and then don't create a new branch. Looks like $1

null-ref will be here too.)


1 The only way to get the post test hook to launch on git clone

is to install the git clone

alignment hook after testing. This is usually not possible, but it can be done by pointing your git to your own template directories which have actual hooks, not just hook patterns.

+1


source


ORIG_HEAD

should be replaced with HEAD@{1}

, as noted in this question ORIG_HEAD

, this is an older, less reliable way to supposedly get the previous state from HEAD. In my case, it was not installed.



+2


source







All Articles