【问题标题】:Is there a way to trigger a hook after a new branch has been checked out in Git?在 Git 中签出新分支后,有没有办法触发挂钩?
【发布时间】:2010-11-03 22:29:09
【问题描述】:

有没有办法在 Git 中签出新分支后触发挂钩?

【问题讨论】:

    标签: git githooks


    【解决方案1】:

    如果这些钩子中的一个不能做到这一点,我会感到惊讶:

    https://schacon.github.io/git/githooks.html

    也许this one:

    结帐后

    当一个 git-checkout 之后运行 更新了工作树。钩子是 给定三个参数: previous HEAD,新 HEAD 的 ref (可能会或可能不会改变), 和一个标志,指示是否 结帐是一个分支结帐 (更改分支,flag=1)或文件 结帐(从 索引,标志=0)。这个钩子不能 影响 git-checkout 的结果。

    【讨论】:

    • 请注意,post-checkout 钩子也适用于 git switch,而 post-switch 钩子没有(从 gi​​t 2.25 开始)。
    【解决方案2】:

    git hook 是放置在存储库的特殊位置的脚本,该位置是:

    .git/钩子

    脚本可以是您可以在您的环境中执行的任何类型,例如 bash、python、ruby 等。

    结帐后执行的钩子是post-checkout。来自文档:

    ...钩子被赋予三个参数...

    示例:

    1. 创建钩子(脚本):

      touch .git/hooks/post-checkout
      chmod u+x .git/hooks/post-checkout
      
    2. Hook 示例内容:

    #!/bin/bash                                                                      
    
    set -e                                                                           
    
    printf '\npost-checkout hook\n\n'                                                
    
    prevHEAD=$1                                                                      
    newHEAD=$2                                                                       
    checkoutType=$3                                                                  
    
    [[ $checkoutType == 1 ]] && checkoutType='branch' ||                             
                                checkoutType='file' ;                                
    
    echo 'Checkout type: '$checkoutType                                              
    echo '    prev HEAD: '`git name-rev --name-only $prevHEAD`                       
    echo '     new HEAD: '`git name-rev --name-only $newHEAD`
    

    注意:第一行的shebang表示脚本的类型。

    这个脚本(git hook)只会捕获传递的三个参数,并以人性化的格式打印出来。

    【讨论】:

    • 你知道有什么方法可以判断这是否是分支创建结帐(除了查看新 HEAD 的 reflog)吗?
    • 似乎对您来说提出一个全新的问题是个好主意。如果你这样做,请将链接发给我,我会看看我是否可以提供帮助。您要解决的问题是什么?
    • 如果一个提交是几个分支的顶部,name-rev 只给出按字母顺序排在第一位的名称。因此,在签出一个名称按字母顺序位于原始分支名称之前的分支后,prev HEAD 行将给出新分支的名称。解决方法:thisBranchName=$(git rev-parse --abbrev-ref HEAD); for branch in $(git branch --color=never --contains $1 | sed -e 's/^..//'); do if [ "$(git show-ref -s $branch )" == $1 ] && [ "$branch" != "$thisBranchName" ]; then parentBranchName=$branch; break; fi; done
    • 谢谢,chmod u+x .git/hooks/post-checkout 部分让我受益匪浅。
    【解决方案3】:

    post-checkouthook接收三个参数:

    1. 上一个 HEAD 的参考
    2. 新 HEAD 的参考
    3. 这是文件检出 (0) 还是分支检出 (1)

    您可以利用从当前 HEAD 创建的分支将具有相同的参数 1 和 2 值这一事实。

    cat > .git/hooks/post-checkout <<"EOF"
    if [ "$3" == "0" ]; then exit; fi
    if [ "$1" == "$2" ]; then 
      echo "New branch created. (Probably)."
    fi
    EOF
    
    chmod u+x .git/hooks/post-checkout
    

    限制:

    • 检出恰好与当前 HEAD 位于同一 HEAD 的现有分支会欺骗它。
    • 不会检测到从当前 HEADnot 创建新分支。

    【讨论】:

      【解决方案4】:

      与其他类似,但验证分支已签出一次。

      #!/bin/bash
      
      # this is a file checkout – do nothing
      if [ "$3" == "0" ]; then exit; fi
      
      BRANCH_NAME=$(git symbolic-ref --short -q HEAD)
      NUM_CHECKOUTS=`git reflog --date=local | grep -o ${BRANCH_NAME} | wc -l`
      
      #if the refs of the previous and new heads are the same 
      #AND the number of checkouts equals one, a new branch has been created
      if [ "$1" == "$2"  ] && [ ${NUM_CHECKOUTS} -eq 1 ]; then
          git push origin ${BRANCH_NAME}
      fi
      

      【讨论】:

      • 这让我走上了正确的道路,非常感谢!由于它是 grepping reflog 来计算结帐,我相信一个问题是如果以前存在一个分支并且创建了一个具有相同名称的新分支,那么该分支将不会被识别为新分支。这可能是所需的行为或问题,具体取决于用例,但我只是想我会提到它。
      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 2017-05-03
      • 2011-01-29
      • 2017-03-18
      • 1970-01-01
      相关资源
      最近更新 更多