[RFC PATCH] hooks--pre-push.sample: identify branch point

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux