1. 11

  2. 2

    The most important Git hook is “post-update” on a remote test repository that can update the working copy after you push to it, run tests and conditionally push to a production repo.

    1. 2

      I use the post-receive hook to checkout, build and deploy a couple of small services on my personal server (blog, wiki, an irc bot, …). Works reasonably well and has this heroku-like feeling.

    2. 2

      Git hooks are so simple yet so good. I have a static site and use a pre-push to generate the files then sync them over to my hosting provider prior to pushing to my git repo.

      1. 1

        On the quality of life side of things, I get a lot of use out of these two hooks that print what I just pushed or pulled, which keeps me aware of incoming changes or what I just sent upstream.

        # After pulling, show a graph of the changes that came in.
        pre-pull.incoming = $HG id -n -r tip > $($HG root)/.hg/tip-pre-pull
        post-pull.incoming = OLDTIP=$(cat $($HG root)/.hg/tip-pre-pull) && $HG slog --pager=none -r "rev($OLDTIP):tip - rev($OLDTIP)"
        # Show graph of outgoing changes before pushing
        pre-push.outgoing = $HG outgoing --graph `echo ${HG_ARGS#push} | sed 's/--new-branch//'`

        I’ve also got a rather neat hook that prevents commits that add trailing whitespace, unless they’re merge commits.

        1. 1

          If you’re using Node, Husky and lint-staged are nice additions. Husky sets up git hooks to execute any npm scripts with a matching name (e.g. precommit). Lint-staged passes only the staged set of files along to any linter or other check you’d like to run in your precommit hooks.

          1. 3

            No, lint-staged is another example of poorly thought out solution that is popular in the node ecosystem. lint-staged doesn’t run the linter against what is going to be committed, instead it runs the linter against the file as it is on disk. Their ‘solution’ for this is to run git add at the end, disregarding if the developer hadn’t staged everything!

            The solution I came up with at $WORK doesn’t automatically fix the code int the precommit hook because if I modify the staged version of the file, it is not trivial to determine what modifications belong to the staged chunks and which don’t. I only reject files that don’t pass the linter and print the linter report.

            When prepending : to the filename git show prints to standard output the staged version of a file. Node is good at handling streams so writing a script that runs ESLint/prettier/stylelint against the staged versions of the files is a less than a 100 lines of code. The gist of the idea is:

            #!/usr/bin/env node
            const { promisify } = require('util');
            let { exec } = require('child_process');
            exec = promisify(exec);
            const ESLintCLIEngine = require('eslint').CLIEngine;
            const cli = new ESLintCLIEngine({});
            const formatter = cli.getFormatter();
            function lintFile(filepath) {
              return exec(`git show :${filepath}`).then(ret => {
                const report = cli.executeOnText(ret.stdout, filepath);
                if (report.errorCount > 0 || report.warningCount > 0) {
                  const errorResults = ESLintCLIEngine.getErrorResults(report.results);
                return report.errorCount === 0 && report.warningCount === 0;
            function lintFiles(filepaths) {
              return Promise.all(filepaths.map(lintFile));