一些不常使用但有趣的 Git 命令

Published on Nov 23, 2022

判断分支是否已经合并到主干

# 判断第一个分支是其他分支的祖先吗
git merge-base --is-ancestor your/feature-brance origin/master

该命令不会有任何输出, 如果 “是”,返回值为 “0”; 如果不是,返回值为 “1”.

gitlab 上查看分支列表时,对于已合并的分支会有一个 merged 的标签,maybe 就是用这种方式实现的。

删除所有已合并到主干的分支

# 删除本地分支
git branch --merged | xargs git branch -d
# 删除远程分支
git branch -r --merged | sed 's/origin\///' | xargs -I {} git push origin :{}

忽略项目中某些文件, 但不放在 .gitignore 文件中

在团队合作的项目中, 你使用了某些大家不常用的工具等,可能会在项目根目录下生成一些配置文件等。

因为不常用,所以极大概率没有加入到 .gitignore 文件中。 为了避免提交代码时受到这些文件的困扰(误提交),我们可以在本地忽略掉这些文件。

echo "/your-some-file" >> .git/info/exclude

参考:gitignore

比较本地文件和某[远程]分支上的文件差异

git diff origin/dev -- path/to/filename

使用 git-hooks 设置受保护的分支(禁止推送)

在团队开发中, 一般都有权限管理的, 比如 master 分支只允许 Team Leader 点合并。 开发者是没有权限直接推送到 master 分支的。

但作为 Team Leader, 即便有权限直接推送到 master 分支, 最佳实践还是不要这么干的好。 更可怕的是,今天由于误操作,将还在开发中的代码直接 push 到了 master 分支, 惊出一身冷汗。

为了避免再次发生这种情况,可通过 .git/hooks/pre-push 来实现禁止推送到某些受保护的分支。

#!/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 oid> <remote ref> <remote oid>

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

protected_branch="main"
protected_remote_ref="refs/heads/${protected_branch}"
while read local_ref local_oid remote_ref remote_oid
do
    # echo "$local_ref" "$local_oid" "$remote_ref" "$remote_oid"
    if test "$remote_ref" = "$protected_remote_ref"
    then
        echo >&2 "分支 ${protected_branch} 为受保护的分支, 不允许推送"
        exit 1
    fi
done

exit 0