2016-02-19 57 views
4

我正在編寫一個預先提交的鉤子來運行我的Python測試,並且所有的工作都很好......直到遇到合併衝突。在此合併衝突,一些文檔文件出臺已經尾隨空白每次我嘗試提交的時候,我得到的消息:git reset --hard -q產生有關空白的錯誤

<stdin>:28: trailing whitespace. 
Ticket Link: 
<stdin>:54: trailing whitespace. 
Then visit `http://app.dev` 
<stdin>:13528: trailing whitespace. 
          //most be provided for ALL resource updates, and 
<stdin>:13531: trailing whitespace. 
    "deleted": false, //indicates if this action resulted in a resource delete; 

warning: squelched 415 whitespace errors 
warning: 420 lines add whitespace errors. 
fatal: could not open '.git/MERGE_HEAD' for reading: No such file or directory 

,然後當我打開我的編輯寫的提交信息,這是完全空。

我提交前的腳本是:

#!/bin/sh 

RED='\033[0;31m' 
NC='\033[0m' 

proper_pop() { 
    git reset --hard -q 
    git stash apply -q --index && git stash drop -q 
} 

exit_and_pop() { 
    proper_pop 

    if [ "$1" -ne 0 ]; then 
     echo "${RED}Your code failed the pre-commit hook! Please examine the output and fix your issues!${NC}" 
    fi 

    exit $1 
} 

run_and_bail() { 
    bash -c "$1"; 
    ret=$?; 

    if [ "${ret}" -ne 0 ]; then 
     exit_and_pop "${ret}" 
    fi 
} 

if git rev-parse --verify HEAD >/dev/null 2>&1 
then 
    against=HEAD 
else 
    # Initial commit: diff against an empty tree object 
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 
fi 

old_stash=$(git rev-parse -q --verify refs/stash) 
git stash -q --keep-index 
new_stash=$(git rev-parse -q --verify refs/stash) 

if [ "$old_stash" = "$new_stash" ]; then 
    echo "pre-commit script: No changes to test. Not running." 
    sleep 1 # HACK: Editor may erase message if done too quickly, make the programmer read 
    exit 0 
fi 

# If you want to allow non-ASCII filenames set this variable to true. 
allownonascii=$(git config --bool hooks.allownonascii) 

# Redirect output to stderr. 
exec 1>&2 

# Cross platform projects tend to avoid non-ASCII filenames; prevent 
# them from being added to the repository. We exploit the fact that the 
# printable range starts at the space character and ends with tilde. 
if [ "$allownonascii" != "true" ] && 
    # Note that the use of brackets around a tr range is ok here, (it's 
    # even required, for portability to Solaris 10's /usr/bin/tr), since 
    # the square bracket bytes happen to fall in the designated range. 
    test $(git diff --cached --name-only --diff-filter=A -z $against | 
     LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 
then 
    cat <<\EOF 
Error: Attempt to add a non-ASCII file name. 
This can cause problems if you want to work with people on other platforms. 
To be portable it is advisable to rename the file. 
If you know what you are doing you can disable this check using: 
    git config hooks.allownonascii true 
EOF 
    exit_and_pop 1 
fi 

if ! [ -z "$(which git-pylint-commit-hook)" ]; then 
    run_and_bail "git-pylint-commit-hook" 
fi 

if ! [ -z "$(which pep8)" ]; then 
    run_and_bail "python hooks/pep8-hook-check.py" 
fi 

proper_pop 

通過我的調試,我公司生產的最小腳本下重現此錯誤是:

#!/bin/sh 

RED='\033[0;31m' 
NC='\033[0m' 

proper_pop() { 
    git reset --hard -q 
    git stash apply -q --index && git stash drop -q 
} 

exit_and_pop() { 
    proper_pop 

    if [ "$1" -ne 0 ]; then 
     echo "${RED}Your code failed the pre-commit hook! Please examine the output and fix your issues!${NC}" 
    fi 

    exit $1 
} 

run_and_bail() { 
    bash -c "$1"; 
    ret=$?; 

    if [ "${ret}" -ne 0 ]; then 
     exit_and_pop "${ret}" 
    fi 
} 

if git rev-parse --verify HEAD >/dev/null 2>&1 
then 
    against=HEAD 
else 
    # Initial commit: diff against an empty tree object 
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 
fi 

old_stash=$(git rev-parse -q --verify refs/stash) 
git stash -q --keep-index 
new_stash=$(git rev-parse -q --verify refs/stash) 

if [ "$old_stash" = "$new_stash" ]; then 
    echo "pre-commit script: No changes to test. Not running." 
    sleep 1 # HACK: Editor may erase message if done too quickly, make the programmer read 
    exit 0 
fi 

proper_pop 

通過這一點,我已經瞭解到,行:git reset --hard -qproper_pop是唯一的罪魁禍首(刪除它刪除錯誤)。沒有安裝其他鉤子,git版本爲:1.8.1.2,但我也在版本2.5.0上運行此版本,並且發生同樣的問題。有沒有人有任何想法發生了什麼?

我嘗試管道輸出和錯誤,以/dev/null爲一個命令,只是爲了看看它是否正常工作,並仍在印刷的錯誤...

它完全是一個問題,我可以解決,它確實沒有按這不會引起任何問題,但我不希望一個技術較低的同事看到這個錯誤並將其拋出(我不確定是否每次我們合併時都會打印這些內容尾隨空格),所以我很想知道發生了什麼以及如何解決這個問題(或者告訴git reset忽略尾隨空白錯誤)。

編輯:

這是一個完整的工作回購演示此問題:https://github.com/hjc1710/so-git-hook-question,只是遵循README.md的步驟,你會得到錯誤,無論你是在合併或不。

我的git配置(對於我的工作站,這是在1.8.x,我的筆記本電腦,在2.5.x)可以找到here。敏感信息已被刪除,但沒有一個是相關的。

+1

運行重置 - 硬盤存儲看起來像預先提交的災難配方。在git嘗試做同樣的事情的時候,你放鬆了舞臺並改變了HEAD。另外,如果你在合併過程中進行git重置,你基本上會中止合併。也許不使用預先提交,而是使用分段分支。然後用一個CI系統的工作流程來測試分段和合並,以便爲您掌握。 – Sukima

+0

我試圖看看標準輸入的差異,因爲這是什麼抱怨來自(':28'),但語法似乎並不存在。您是否確認了預安裝鉤子會在乾淨的機器上導致與全新安裝的git相同的問題?運行你的腳本對我來說不會產生任何錯誤,但是這些錯誤看起來讓人聯想到'git rebase --whitespace = warn'這樣的警告。我希望看到你的repo,global和system .gitconfigs('git config -l','git config --global -l','git config --system -l')。 – Bujiraso

+0

@Bujiraso我已經用我的git configs(我的筆記本電腦上的2.5.x和我的工作站上的1.8.x)編輯了我的原始問題,並使用剝離下鉤和單個文本演示了這個確切問題的示例回購文件。無論您是否在合併中,都會發生錯誤,並且掛鉤只是用索引存儲,並且在沒有索引的情況下正確地掛起。我沒有安裝全新機器的簡易機器,但是如果您想要與他們一起玩,那麼回購中的這些說明應該在100%的時間內觸發錯誤。我有**沒有**的想法,這是得到管道git diff。謝謝! – hjc1710

回答

3

作爲this answer指出的第二個腳註,git stash apply僅僅調用git diff ... | git apply --index。警告來自這些命令。

發生這種情況時,您有尾隨空格,存儲包含尾隨空格的文件,然後應用藏匿。 更準確地說它發生如果您創建了尾隨空白一個git補丁,並嘗試通過cat a.patch | git diff --index,同樣的錯誤結果運用它,你嘗試git apply尾隨換行到代碼

身體的任何時間。

作爲解決這個問題, 它會站在有理由相信,在本地,全局或系統 gitconfig設置 core.whitespace=nowarn會沉默,但是這似乎並沒有爲我是真實的,但情況因人而異。 (這些設置沒有被讀取,看來)。 運行git config core.whitespace -blank-at-eol,正如評論中指出的那樣。

我看到的唯一的解決方案,除上述以外,就是找到在混帳藏匿bash腳本出錯行和--whitespace=nowarn參數添加到git apply,自己。我應該提到的是一個相當不標準的非便攜式解決方案。你必須讓每個人都這樣做,很可能每次都是git更新。但是,如果他們打擾你沒有結束 - 這就是你可以做的。

正如你所提到的那樣,它可以被解決,但它可能是值得在git上打開一個bug本身,如果我沒有弄得一團糟,它是 甚至忽略了 系統 gitconfig。我希望它至少應該兌現。

+0

如果你想要一個命令來替換那一行,下面的代碼爲我工作:'sudo sed -ie'/ git diff。* git apply/s/apply --cached/apply --cached --whitespace = nowarn /' [git-stash腳本的位置]'。對我來說,它位於'/ usr/lib/git-core/git-stash'中。 – Bujiraso

+1

可以確認,如果你打開'/ usr/lib/git-core/git-stash'並更新行'422'爲:'git diff-tree --binary $ s^2^.. $ s^2 | git apply --whitespace = nowarn --cached',**整個問題**消失。然而,你是100%正確的,那是**不是可移植的,並且是可怕的**事情,所以這不是我要做的事情。但是,我認爲你正在做你的git配置有點不對。如果我編輯我的本地git配置('.git/config')並添加'core.whitespace = nowarn',它不起作用,並且查看文檔,這不是支持的命令,而是添加了'core.whitespace = -blank-at-eol'工程! – hjc1710

+1

我想我會在git上打開一個問題,說'git stash apply'也應該尊重'--whitespace = nowarn',就像'git apply'一樣,但我認爲這不是一個比那更大的bug 。非常感謝你的時間和精力!你真的做了一些工作來狩獵這一個,找出錯誤並提出解決方案(我將最終使用)。你贏得了這個賞金和正確的答案! – hjc1710

2

爲了讓您很容易重現您的榮譽!

這個問題似乎是該鉤內的GIT中命令被寫入空白錯誤到當前tty代替stdoutstderr。然後,鉤亞軍拿起錯誤,然後錯誤地聲稱它是stdout

該修補程序來自the answer爲我之前的一個問題。

#!/bin/sh 
git stash > /dev/null 
unbuffer sh -c 'git stash apply -q --index && git stash drop -q ' >/dev/null 2>&1 

編輯:如果你想在OSX的非緩衝程序,您可以使用說明here得到它。

brew tap homebrew/dupes/expect 
brew install homebrew/dupes/expect 
+0

我很高興能讓這個測試變得如此簡單!這是一個難以解釋的問題,所以我認爲回購更容易。另外,非常感謝您的回答和迴應!不幸的是,'unbuffer'沒有默認安裝,我有**不知道**如果它適用於OSX或OSX模擬器(我有大約8個OSX傢伙),我真的不想帶外包,所以我不會接受你的答案。你做了一件非常棒的工作,告訴我**爲什麼**這是繞過'>/dev/null 2>&1',我非常感謝你,但我更喜歡編輯本地'gitconfig'的答案! – hjc1710

+0

沒有必要證明不接受答案。我很高興你從中學到了一些東西。 :) – merlin2011

+0

謝謝!我真的很感激你的時間,我總是喜歡學習TTY和僞TTY,他們絕對是**迷人的**。 – hjc1710

相關問題