在 "git checkout -b" 命令后触发 post-checkout 钩子

Triggering post-checkout hook after "git checkout -b" command

之前有人问过同样的问题here,但是这两个答案对我帮助不大。

我无法让我的 post-checkout 钩子将 git checkoutgit checkout -b 命令区别为 </code>(前一个 HEAD 的 sha1)和 <code>(新 HEAD 的 sha1) 两个调用都相同。

这是我的 post-结帐脚本:

#!/bin/bash

echo "old HEAD: "
echo "new HEAD: "
echo "checkout type: "

我执行了以下命令:

> ozgur@ozgurv:~/project (master)$ git checkout -b new_branch
old HEAD: e86423aa9f45053cb45b8ec15d463bb9684526a2
new HEAD: e86423aa9f45053cb45b8ec15d463bb9684526a2
checkout type: 1

> ozgur@ozgurv:~/project (new_branch)$ git checkout my_branch
old HEAD: e86423aa9f45053cb45b8ec15d463bb9684526a2
new HEAD: e86423aa9f45053cb45b8ec15d463bb9684526a2
checkout type: 1

我想要实现的是仅在创建新的本地分支时执行 post-checkout 挂钩中的逻辑,而不是在签出时执行。

在 post-checkout hook 中,您无法真正分辨出区别。1 无论如何您可能 想要 来尝试区分。考虑:

$ git branch newbr     # make a new branch
$ git checkout newbr   # and now check it out

在这里为 git checkout -b newbr 做任何事情可能是有意义的,如果是这样,检查 -b 标志(如果可以让它工作)可能会适得其反。 (还要考虑 git checkout featureorigin/feature 存在而本地分支 feature 不存在时,这会创建 feature 作为跟踪 origin/feature 的新分支,即使再次存在没有 -b 标志。)

让我们再看一遍,我会建议一个不同的方法:

only when a new local branch is created

如果在您的挂钩中,您将 "all seen-so-far local branches" 的列表保存在文件中怎么办? (也许 .git/ozgur/branchlist 是一个合理的地方来保留它。我们想要一些跟在存储库周围的东西, git 本身不太可能使用。)然后,如果结帐是分支式结帐( </code> is <code>1), 将当前分支与列表进行比较:

git_dir=$(git rev-parse --git-dir) || exit 1
branchlist=$git_dir/ozgur/branchlist
if [ "" = 1 ]; then
    # Checked out a branch - what branch are we on now?
    # (Skip rest of code if we're on a detached HEAD.)
    curbranch=$(git symbolic-ref --short HEAD) || return
    # Is $curbranch in our branch list?  Create empty
    # branch list first if needed.  Can just "touch" but
    # this avoids changing the mod-time unnecessarily.
    [ -f $branchlist ] || : > $branchlist
    if ! grep "^$curbranch$" $branchlist > /dev/null; then
        echo "switching to as-yet-unvisited-branch $curbranch"
        echo $curbranch >> $branchlist  # now we've visited it
    fi
fi

这还是有点瑕疵的:如果你删除了一个分支,它可能会留在branchlist文件中。我们可以通过相当定期地过滤掉已删除的分支来解决这个问题(将 $branchlist 内容与适当的 git for-each-ref refs/heads 输出进行比较),也许在额外的 git 挂钩中也是如此。但它可能足以满足您的目的。


1实际上,一种判断方式,至少在让您查看进程树的系统上是这样,并且查看他们的命令参数。从挂钩中,找到您的父 git checkout 进程并查看它是否具有 -b 标志。但是它不适用于两步 git branch ...; git checkout 序列,也不适用于从上游分支自动创建的分支。