35

I have added something like that in pre-push hook:

gs0=$(git status)
pip-dump
gs1=$(git status)
if [ "gs0" != "gs1" ]
then
    git commit -m "pip-dump"
fi

(this is updating my pip requirements file)

It seems that the push is not pushing the new commit, but the one which the HEAD was on at the beginning of the script.

How to fix that?

lajarre
  • 4,910
  • 6
  • 42
  • 69

2 Answers2

38

You can't: the push command figures out which commits to push before invoking the hook, and pushes that if the hook exits 0.

I see three options:

  1. Exit nonzero, telling the user "push rejected because I added a commit"
  2. Exit zero, telling the user "push went through but you'll need to push again because I added a commit"
  3. Do another (different) push inside the hook, after adding the new commit, taking care that your hook does not endlessly recurse because the "inner" push runs the hook which decides to do another "inner-again" push, etc. Then, exit nonzero, aborting the "outer" push, after announcing that you had to do an "inner" push to get the extra commit sent through.

My personal preference would be the first of these. A pre-push hook is meant as a "verify that this push is OK" operation, not a "change this push to mean some other different push" operation. So that means you're not working against the "intent" of the software. Use the pre-push hook as a verifier; and if you want a script that invokes git push after automatically adding a pip-dump commit if needed, write that as a script, using a different name, such as dump-and-push.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 3
    I am ok that option 1 is the best. But the `dump-and-push` solution is not good for me because I have no confidence in myself or my team in not forgetting that `git push` is not to be used. – lajarre Jan 24 '14 at 14:31
  • 2
    Well, in rejecting a push because a dump is required, you can emit a line saying "by the way, if you use this other script, it would Just Work, won't that be easier? hint hint! :-)" – torek Jan 24 '14 at 14:36
  • @lajarre how can you be confident your team have installed the hook? Long term hiding that in git push will probably become an issue of some kind. – AD7six Jan 24 '14 at 14:54
  • 2
    @AD7six has a good point: if you *really* want enforcement, you need a to use a pre-receive or update hook on the centralized server. – torek Jan 24 '14 at 15:01
  • 2
    thanks, @torek! I need to run `npm version patch` before every push to manage versions automatically. So I use the option 1, it works great! https://github.com/wechaty/wechaty/blob/8a32376b07e53ea28e694a2d854af00e2b426d9e/bin/pre-push – Huan Nov 10 '16 at 13:58
  • 6
    for option 3, you may call `git push --no-verify` in your script to make a push without invoking the hook again – Pnar Sbi Wer Oct 26 '17 at 08:26
0

To complement torek's answer, here is a way in PowerShell to perform a variant on option #3.

Do another (different) push inside the hook, after adding the new commit, taking care that your hook does not endlessly recurse because the "inner" push runs the hook which decides to do another "inner-again" push, etc.

The difference is that we exit zero and do the "inner" push after completing the "outer" push.

pre-push

#!/bin/sh

dir=$(dirname "$0")

pwsh -NoProfile -File "$dir/pre-push.ps1";

pre-push.ps1

Register-EngineEvent PowerShell.Exiting -SupportEvent -Action {

  Write-Host "Registering post-formatting job.";

  try {
    $waitCommand = "while((git status -sb) -match 'ahead') { Start-Sleep -Seconds 1; };";
    $gitCommand = "git commit --allow-empty -m 'format'; git push --no-verify;"
    Import-Module Microsoft.PowerShell.Management;
    Start-Process pwsh `
      -WindowStyle Hidden `
      -ArgumentList "-NoProfile -Command $waitCommand $gitCommand";
  } catch {
    Write-Host $_;
  }

  Write-Host "Registered post-formatting job.";
}

# --------------
# Perform the auto-formatting here.
# --------------

exit 0;

The scenario is auto-formatting, but it could be any task that changes the code before making a commit and push.

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467