簡體   English   中英

預提交鈎子中的git stash在第一次提交時失敗

[英]git stash in pre-commit hook fails on first commit

我正在研究一個使用YUI Compressor的預提交鈎子,以最小化已准備提交的任何CSS和JavaScript文件。 縮小文件后,縮小的版本會自動上載以供提交。 我已經讀到,自動將機器生成的文件添加到提交中通常不是一個好主意,但是我認為在這種情況下可以。 看起來是這樣的:

git status輸出:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   _site-wide.css
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   _subpage.css
#

git commit -m "Updated site-wide styling"

1 CSS file was minified and added to the Git repository
0 JavaScript files were minified and added to the Git repository
[master 41f1815] Updated site-wide styling
 2 files changed, 2 insertions(+), 2 deletions(-)

此處發生的是使用YUI Compressor最小化_site-wide.css的預提交鈎子,將結果輸出到site-wide.css (無下划線)。 然后,它上演site-wide.css進行提交。 pre-commit鈎子跳過了_subpage.css因為盡管已對其進行了修改,但尚未上載它。

由於磁盤上的CSS和JavaScript文件可能與為提交而暫存的CSS和JavaScript文件不同,因此我在縮小文件之前先運行git stash -q --keep-index ,然后再運行git stash pop -q 這個預先提交的鈎子在已經具有提交的存儲庫上可以正常工作,但是如果我在進行第一次提交之前將預先提交的鈎子放在適當的位置,我會得到:

git status輸出:

# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   _site-wide.css
#   new file:   _subpage.css
#

git commit -m "Initial commit"

fatal: bad revision 'HEAD'
fatal: bad revision 'HEAD'
fatal: Needed a single revision
You do not have the initial commit yet
2 CSS files were minified and added to the Git repository
0 JavaScript files were minified and added to the Git repository
No stash found.

git status輸出:

# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   _site-wide.css
#   new file:   _subpage.css
#   new file:   site-wide.css
#   new file:   subpage.css
#

現在,我將粘貼預提交的鈎子代碼。 請記住,為了靈活起見,我編寫了此腳本,以便可以在任何CakePHP項目中運行它,而不僅僅是具有Git存儲庫的項目。 我還編寫了它,以便您可以強制它縮小所有CSS和JavaScript文件,而不僅僅是縮小提交階段。 這是通過運行.git/hooks/pre-commit force 這是代碼:

#!/bin/bash

css_files_to_ignore=(
    #"_do_not_minify.css"
)

js_files_to_ignore=(
    #"_do_not_minify.js"
)

if git rev-parse --git-dir > /dev/null 2>&1; then
    git_repository=true
    base_folder="$(git rev-parse --show-toplevel)/app/webroot"

    if [ "$1" == "force" ]; then
        process_unstaged_files=true
    else
        process_unstaged_files=false
    fi
else
    git_repository=false
    base_folder="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/webroot"
fi

if [ -f /Applications/yuicompressor.jar ]; then
    # Mac

    yuicompressor_path=/Applications/yuicompressor.jar
else
    # Linux

    yuicompressor_path=$(command -v yui-compressor)
fi

function process_assets()
{
    extension=$1
    files_minified=0

    for infile in $(echo "$base_folder/$extension/*.$extension")
    do
        # Only process files.

        [[ -f $infile ]] || continue

        filename=${infile##*/}

        # If the filename starts with an underscore, that means that the file is
        # eligible for minification.

        [[ ${filename:0:1} == "_" ]] || continue

        ignore_this_file=false

        files_to_ignore=$extension"_files_to_ignore"

        for i in $(eval echo \${$files_to_ignore[@]})
        do
            if [[ $i == $filename ]]; then
                ignore_this_file=true
                break
            fi
        done

        if [ $git_repository == true ] && [ $process_unstaged_files == false ] && git diff --quiet --cached $infile; then
            # This file is NOT staged for commit.

            ignore_this_file=true
        fi

        if [ $ignore_this_file == false ]; then
            minified_file="$base_folder/$extension/${filename:1}"

            if [ ! -f "$minified_file" ] || test $infile -nt $minified_file; then
                $yuicompressor_command "$infile" -o "$minified_file"

                if [ $git_repository == true ] && [ $process_unstaged_files == false ]; then
                    git add "$minified_file"
                fi

                ((files_minified++))
            fi
        fi
    done

    # Output a summary of what was done.

    if [ $extension == "css" ]; then
        file_type="CSS"
    else
        file_type="JavaScript"
    fi

    echo -n "$files_minified $file_type file"

    if [ $files_minified -eq 1 ]; then
        echo -n " was"
    else
        echo -n "s were"
    fi

    echo -n " minified"

    if [ $git_repository == true ] && [ $process_unstaged_files == false ]; then
        echo " and added to the Git repository"
    else
        echo
    fi
}

if [ -f "$yuicompressor_path" ]; then
    if [ ${yuicompressor_path: -4} == ".jar" ]; then
        yuicompressor_command="java -jar $yuicompressor_path"
    else
        yuicompressor_command=$yuicompressor_path
    fi

    if [ $git_repository == true ] && [ $process_unstaged_files == false ] && ! git diff --quiet --cached; then
        # The staging area is what should be processed rather than what is currently
        # on disk.

        git stash -q --keep-index

        stashed=true
    else
        stashed=false
    fi

    process_assets css
    process_assets js

    if [ $stashed == true ]; then
        git stash pop -q
    fi
else
    echo "YUI Compressor was not found. Aborting."
    exit 1
fi

我該如何進行這項工作? 任何幫助,將不勝感激。

我得出的結論是,對此沒有解決方案,因為在沒有HEAD的情況下,某些Git命令根本無法工作。 另外,經過更多考慮之后,我認為無論如何,至少對於我而言,這是一種邊緣情況,因為我的第一次提交通常是一些基本的東西,例如我使用的框架文件。 因此,我可以在第一次提交后實施鈎子。

我感謝Hassek的時間以及其他閱讀此書的人的時間。 謝謝!

在Git 2.22(2019年第二季度,7年后)中,有一個, git stash用C重寫

參見Paul-Sebastian Ungureanu( weekly-digest[bot] 提交1ac528c (2019年2月25日

stash :使push -q安靜

此提交的行為有所變化。
如果沒有初始提交,則stash的shell版本仍會顯示一條消息。
如果指定了--quiet-q則此提交使push不顯示任何消息。

因此,您應該不會從git stash -q <command>看到“ You do not have the initial commit yet ”,從Git 2.22的新的C語言stash命令開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM