Git钩子预推提示来壁球首先提交 [英] Git hook pre-push prompt to squash commits first

查看:152
本文介绍了Git钩子预推提示来壁球首先提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定我是否要采用正确的方法.对Git和GitKraken来说是新的.我想强迫其他人在推送和创建请求请求之前压扁他们的功能分支提交.因此,我尝试了以下预按git钩,但是即使我先将其压扁认为有多个提交.我想念什么?谢谢!

I'm not sure if I'm going about this the correct way. Sorta new to Git and GitKraken. I want to force others to squash their feature branch commits before pushing and creating a pull request. So I've tried the following pre-push git hook but even when I squash first it still thinks there are multiple commits. What am I missing? Thanks!

#!/bin/sh

# An example hook script to verify what is about to be pushed.  Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed.  If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
#   <local ref> <local sha1> <remote ref> <remote sha1>

remote="$1"
url="$2"

z40=0000000000000000000000000000000000000000

while read local_ref local_sha remote_ref remote_sha
do
    if [ "$local_sha" = $z40 ]
    then
        # Handle delete
        :
    else
        # Check for number of commits
        commits=`git rev-list --count "$local_sha"`
        if [ "$commits" -ne "1" ]
        then
            echo "Multiple commits detected, push aborted. Please squash your local branch before pushing."
            exit 1
            #git reset --soft HEAD~"$commits"
            #git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
        fi
    fi
done

exit 0

推荐答案

TL; DR

您要git rev-list --count $local_sha ^$remote_sha(但请参见下面的警告).

TL;DR

You want git rev-list --count $local_sha ^$remote_sha (but see caveat below).

git rev-listgit log的老大哥(姐姐?)管道变体:默认情况下,两者都会开始您给他们的提交,然后找到这些提交中可以到达的每个提交.

git rev-list is the big brother (sister?) plumbing variant of git log: both will, by default, start from the commit(s) you give them, and find every commit reachable from those commits.

也就是说,给定一个提交图,例如:

That is, given a commit graph like:

... <-E <-F <-G   <-- branchname

您告诉Git从branchname开始,它标识了提交G(这里的G代表实际的40个字符的哈希ID),因此git log向您显示该提交.然后,由于GF作为其父级(G指向F),因此git log向您显示F.由于FE作为其父级,因此git log接下来将显示E,依此类推.

you tell Git to start from branchname, which identifies commit G (G here stands in for the actual 40-character hash ID), so git log shows you that commit. Then, since G has F as its parent (G points to F), git log shows you F. Since F has E as its parent, git log shows you E next, and so on.

修订列表代码执行相同的操作:您告诉它从哪里开始-$local_sha-它列出了提交的哈希,其父哈希,以及其父的更多哈希,以及很快.添加--count使其计数,并且可能有很多.

The rev-list code does the same thing: you tell it where to start—$local_sha—and it lists that commit's hash, and its parent(s) hash(es), and more hashes of their parents, and so on. Adding --count makes it count them up, and there are probably many.

您需要告诉沿着图停止位置的Git命令.鉴于:

You need to tell the Git commands that walk the graph where to stop. Given:

E--F--G   <-- branchname

您可以告诉git rev-listG开头(按哈希ID或名称),但要 stop (不包括)E(按哈希ID或依据)名称,如果有指向E的名称).您可以通过多种方式来命名停止点提交,但是最直接的是帽子前缀:^E表示E处停止,或者从E 可以到达的任何提交.

you can tell git rev-list to start at G (by hash ID, or by name), but to stop (and not include) E (by hash ID, or by name if there's a name that points to E). You can name stopping-point commits in many ways, but the most direct is the hat-prefix: ^E means stop at E, or any commit reachable from E.

可达性概念在更复杂的图形中非常重要:

This reachability notion is very important in more complex graphs:

  B--C
 /    \
A      F--G   <-- branchname
 \    /
  D--E

连接提交的箭头(我一直在这里绘制为线)都是单向的:它们都在时间上向后指向.所以F在这里指向EC,因为F在这里是合并提交. C指向B,它指向AE指向D,它也指向A.

The arrows connecting commits (which I've been drawing as lines here) are all one-way: they all point backwards in time. So F points back to both E and C here, because F here is a merge commit. C points back to B, which points back to A; E points back to D, which also points back to A.

如果将E命名为终止点,并且将G命名为起始点,则git rev-list将跳过提交EDA,但是仍将包含提交BC,因为可以从F进行访问.要同时排除BC,必须在停止点列表中添加^C.

If you name E as a stopping point and G as the starting point, git rev-list will skip commits E, D, and A, but will still include commits B and C, because those are reachable from F. To exclude B and C as well, you must add ^C to your list of stopping points.

通常,在预推钩子中,您可以仅将远程哈希列为(单个)停止点,但还有一个更普遍的问题:您可能没有提交远程哈希指向.您可以通过运行git fetch从远程获取提交.它们-您正在访问的另一个存储库-由在此提交的某人或也对该存储库的其他人进行的提交.您可能还没有他们的提交.如果是这样,则必须首先运行git fetch,以便您自己的Git拥有提交,以便您的Git可以从其哈希ID开始遍历提交图.

In general, in a pre-push hook, you can just list the remote hash as the (single) stopping point, but there's a more general problem: you might not have the commit that the remote-hash points-to. You get commits from the remote by running git fetch. They—the other repository to which you are git pushing—get commits by someone committing there, or by other people also git pushing to that repository. You might not have their commit(s) yet. If so, you'll have to run git fetch first, so that your own Git has the commit, so that your Git can walk the commit graph starting from their hash ID.

这篇关于Git钩子预推提示来壁球首先提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆