How to Prevent Commiting to master/develop branch by Accidents u

  • 时间:2020-10-11 16:01:36
  • 分类:网络文摘
  • 阅读:100 次

Have you ever been wanting to push your heads against the walls when you accidentally push commits to the master/develop branchs (even they are local branches)? You can however `git reset HEAD files` to unstage the commits, however, this is not a pleasant thing to do.

Luckily, the git provides many hooks and pre-push is the one that allows you to do some checks before the git actually pushes it. The pre-push is actually a bash script that runs before the `git push` command. If the script returns 1 then nothing happens. It the script returns 0, it will continue the push operation.

The pre-push is located at each reprository under .git/hooks directory, which is hidden. The following is the sample pre-push (named pre-push.sample)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/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><local sha1> <remote ref> </remote><remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
 
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
        if [ "$remote_sha" = $z40 ]
        then
            # New branch, examine all commits
            range="$local_sha"
        else
            # Update to existing branch, examine new commits
            range="$remote_sha..$local_sha"
        fi
 
        # Check for WIP commit
        commit=`git rev-list -n 1 --grep '^WIP' "$range"`
        if [ -n "$commit" ]
        then
            echo >&2 "Found WIP commit in $local_ref, not pushing"
            exit 1
        fi
    fi
done
 
exit 0
#!/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><local sha1> <remote ref> </remote><remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).

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
		if [ "$remote_sha" = $z40 ]
		then
			# New branch, examine all commits
			range="$local_sha"
		else
			# Update to existing branch, examine new commits
			range="$remote_sha..$local_sha"
		fi

		# Check for WIP commit
		commit=`git rev-list -n 1 --grep '^WIP' "$range"`
		if [ -n "$commit" ]
		then
			echo >&2 "Found WIP commit in $local_ref, not pushing"
			exit 1
		fi
	fi
done

exit 0

We can check if the current branch is in one of the master branches e.g. master, origin/develop, if yes, then exit with code 1. The following pre-push script has to be chmod with executable permission. All it does is to check if current branch is forbidden, if yes, return 1 otherwise indicates 0 to continue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
# run `chmod +x .git/hooks/pre-push` (We make the hook executable by using the chmod utility.)
# To bypass this hook and force the push, use 'git push --no-verify'
 
master_branches=('origin/develop' 'master' 'develop')
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
 
for branch in "${master_branches[@]}"
do
    if [ $branch = $current_branch ]; then
        echo "You're about to push $branch and you don't want that"
        exit 1
    fi
done
exit 0
#!/bin/bash
# run `chmod +x .git/hooks/pre-push` (We make the hook executable by using the chmod utility.)
# To bypass this hook and force the push, use 'git push --no-verify'

master_branches=('origin/develop' 'master' 'develop')
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

for branch in "${master_branches[@]}"
do
    if [ $branch = $current_branch ]; then
        echo "You're about to push $branch and you don't want that"
        exit 1
    fi
done
exit 0

Here is how it looks like when you try to push to master:

1
2
3
4
5
$ git branch
* master
$ git push origin master 
You're about to push master and you don't want that
error: failed to push some refs to 'https://github.com/DoctorLai/ACM.git'
$ git branch
* master
$ git push origin master 
You're about to push master and you don't want that
error: failed to push some refs to 'https://github.com/DoctorLai/ACM.git'

As the pre-push has to be on each reprository, you can copy the file at your root direction, and use the following bash command to find and copy the file to all .git/hooks directory.

1
find . -type d -name "hooks" | grep ".git/hooks" | xargs echo cp pre-push
find . -type d -name "hooks" | grep ".git/hooks" | xargs echo cp pre-push

On windows, I guess the pre-push is still written in BASH. However, if the above not working on Windows, you might try the following Windows BATCH script – or just for education purposes.

@echo off
REM pre-push.cmd
REM To bypass this hook and force the push, use 'git push --no-verify'

setlocal enabledelayedexpansion
set branches=origin^/develop master develop

for /f "tokens=2" %%i in ('git branch') do (set current=%%i)
for %%j in (%branches%) do (
    if /i "%%j"=="%current%" (
        echo You're about to push to %%j, you don't want that
        exit /b 1
    )
)
endlocal
exit /b 0

Git has other hooks, for example: The Git Pre-Commit Hook to Avoid Pushing Only Unit Tests In NodeJs

–EOF (The Ultimate Computing & Technology Blog) —

推荐阅读:
蜘蛛蜻蜓蝉各有多少只  鸡兔同笼共306只脚问鸡兔各几只  简算题:(1/8+1/24+1/48+1/80+1/120+1/168+1/224+1/288)×128  奥数题:狗跑5步的时间马跑3步  数学题:甲乙丙三桶油  数学题:将一块圆锥形糕点沿着高切成两半  数学题:这包糖果至少有多少颗  数学题:在1989后面写下一串数字  数学题:三一班图书角中的故事书本数比连环画本数的2倍多8本  数学题:兔妈妈拔回家一筐萝卜 
评论列表
添加评论