The pre-push hook introduced in 87c86dd14a (Add sample pre-push hook script, 2013-01-13) has a pretty naive implementation that inspects the entirety of that branch history, regardless of previous merges. In other words, if you create a topic branch from a current history, the entire history will be inspected by the pre-push hook. In my case, there was an old "WIP" commit log that broke the hook, even though that commit wasn't specific to the branch in question, nor was it introduced by the push. This patch aims at fixing that problem by restricting the revisions inspected when a new branch is pushed to something that is more specific to that branch. This implementation will first attempt to find an ancestor that the current branch is related to (`--merged=`). This is where this implementation is the most questionable; normally you would put `master` or `main` as a base branch, but who knows what people actually use for this nowadays. And besides, it's fair to assume you could be pushing something based on a branch that already exists upstream that is *not* master or main... But still, that's a tricky bit I'm not sure of. Then we find the "branch point" which is the latest commit on the ancestor branch that's shared with the inspected ref. This, interestingly, seems to be a really tricky problem as well. I base my implementation off this answer on Stack Overflow (I know! at least it's not ChatGPT!): https://stackoverflow.com/a/71193866/1174784 There are currently a whopping twenty-five answers to that question in that thread, and I'm hoping the community here will have a more definitive answer to this question. I have picked the answer that uses the least possible external commands, but it still uses a `tail -1` which I'm somewhat unhappy about. I have thought of using `--max-count` for this instead, but I understand that probably does the equivalent of a `head -n` *and* it's applied before `--reverse`, so there's not other way to do this. The final question to answer here is whether this is a good idea in the first place, and whether this is the right place to answer this kind of question. I happen to really like using pre-push (instead of pre-commit) for inspecting my work before submitting it upstream, so it was a natural fit for me, but this might be everyone's taste. As the subject indicates, I would very much welcome comments on this. I would be happy to submit a more elaborate version of this (e.g. with unit tests) if it's interesting for the community, or receive guidance on where best this could be implemented or improved. Signed-off-by: Antoine Beaupré <anarcat@xxxxxxxxxx> --- templates/hooks--pre-push.sample | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/templates/hooks--pre-push.sample b/templates/hooks--pre-push.sample index 4ce688d32b..f871b65195 100755 --- a/templates/hooks--pre-push.sample +++ b/templates/hooks--pre-push.sample @@ -33,8 +33,24 @@ do else if test "$remote_oid" = "$zero" then - # New branch, examine all commits - range="$local_oid" + # new branch + # + # search for a base branch that's part of this branch, latest modified + # + # it's a better heuristic than hardcoding "master" or "main" + base_branch=$(git for-each-ref \ + --merged="$local_ref" \ + --no-contains="$local_ref" \ + --format="%(refname:strip=-1)" \ + --sort='-*authordate' \ + refs/heads ) + # find the place where we branched off the base branch + branch_point=$(git rev-parse \ + $(git rev-list --exclude-first-parent-only \ + ^"$base_branch" "$local_ref"| tail -1)^ \ + ) + # examine all commits up to the branch point + range="$branch_point..$local_oid" else # Update to existing branch, examine new commits range="$remote_oid..$local_oid" -- 2.39.2