2011-04-03 97 views
10

我有一個post-receive掛鉤腳本坐在遠程回購我推到不一個git reset --hard上混帳推硬復位

事情是這樣的:

$ git push opal 
Counting objects: 74, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (45/45), done. 
Writing objects: 100% (53/53), 16.68 KiB, done. 
Total 53 (delta 20), reused 0 (delta 0) 
remote: warning: updating the current branch 
remote: HEAD is now at 88f1e35 tweak lavalamp styles 

什麼,我不明白這裏是 - 遠程表示頭現在在XXX,但是當我登錄到服務器 - 遠程工作副本根本沒有更新!

有什麼想法嗎?

+0

當你遇到問題時,你應該發佈你的鉤子腳本。 – 2011-04-04 03:35:44

+0

Chris,我的post-receive腳本只包含那一行。無需發佈。 – David 2011-04-04 18:51:12

回答

0

那麼腳本可能不會運行。它不會運行在愚蠢的http服務器上。 它會運行在ssh上。我不確定智能http服務器。

如果不是這樣,你應該檢查hook上的'execute'permssion(chmod + x .git/hooks/post-receive)。當你在這裏時,通常檢查owenership和權限。

如果看起來沒問題,只需在腳本中包含一個作爲第一行的日誌語句(例如date "%T $0 executed" >> /tmp/debug_hook.log)並檢查日誌文件以查看是否更新了任何內容。

此外,它可能推動到而不是實際上做任何事情(一切都是最新的)。在這種情況下,有意義的是不叫鉤子

如果所有這些都沒有提示,請發佈.git/config,因爲它駐留在服務器上(或至少部分)。 git log -1 HEAD會在服務器上給出預期的結果嗎?您的鉤子腳本是否包含可能會覆蓋GIT_DIR,GIT_WORK_TREE或GIT_INDEX_FILE的任何內容?

+0

'HEAD現在在......'消息只可能來自'git checkout'或'git reset'。這兩者都不是正常推送的一部分,所以鉤子腳本幾乎肯定會運行。 – 2011-04-04 04:13:07

+0

您是否做過其他檢查?特別是HEAD檢查?讀另一篇文章,你必須在'GIT_DIR'檢查中得到一個積極的結果... – sehe 2011-04-04 06:25:54

22

問題是Git命令在爲鉤子腳本創建的環境與正常環境之間的行爲差​​異。

首先,鉤子腳本以其當前工作目錄設置爲Git目錄本身(即非裸倉庫的.git/目錄)運行。其次,鉤子腳本使用GIT_DIR環境變量集運行,並指向Git存儲庫(同樣是非裸存儲庫的.git/目錄)。

通常情況下,如果你嘗試運行從.git/目錄git reset --hard,它會與下面的消息死:

fatal: This operation must be run in a work tree 

但當GIT_DIR設置,Git命令假設當前目錄是工作樹。由於鉤子運行時的當前目錄是.git/目錄,因此您的git reset --hard實際上是直接將您的工作樹文件「檢出」爲.git/而不是其父目錄(即,您現在在.git/目錄中擁有版本化內容的副本)。

希望版本庫中沒有版本化的內容的路徑名與pathnames that Git uses in Git repositories themselves一致。如果它們一致,那麼你的git reset --hard將覆蓋你的倉庫的一些內部結構,你可能會想從其他倉庫重新克隆它。如果你有信心,沒有使用Git的內部路徑名的版本內容衝突,那麼你可以用這個把它清理乾淨:

# make a backup of your repository first! 
(cd .git && GIT_DIR=$PWD git ls-files -cz | xargs -0 rm) 

這隻會刪除當前跟蹤的文件(它會留下有文件自從被移除後,但是在斷鉤處於活動狀態時曾經被推入提示提交中)。


一種解決方法是調用Git命令之前,改變當前工作目錄到正常工作樹和取消GIT_DIR和GIT_WORK_TREE。

⋮ 
test "${PWD%/.git}" != "$PWD" && cd .. 
unset GIT_DIR GIT_WORK_TREE 
# you can now safely use Git commands 
⋮ 

另一種解決方案是顯式重置GIT_DIR,在那裏設置GIT_WORK_TREE和chdir。 Git FAQ 「Why won't I see changes in the remote repo after "git push"?」建議post-update script這樣做。鏈接的腳本也更加安全,因爲如果索引或工作樹在執行硬重置之前變髒,它會進行存儲。

+0

優秀的東西,謝謝 – sehe 2011-04-04 06:29:02

+1

+1 Aargh,這是可怕的。更糟糕的是,我之前沒有意識到$ PWD和$ GIT_DIR在非裸倉庫中運行時對於不同的鉤子是不一致的。 (例如,在'post-commit'中,它們分別設置爲工作樹和'.git'。) – 2011-04-09 08:02:14

+0

@Mark:嗯,我沒有考慮到「本地」鉤子。它看起來可能只是設置這個有問題的環境的「遠程」掛鉤(接收和更新變體)。其他鉤子主要針對那些需要工作樹的活動,而且它們似乎是用一個理想的配置運行的,它需要一個工作樹(這很有意義,因爲這些鉤子通常是從需要工作樹的命令調用的) 。 – 2011-04-09 09:36:52

13

總之,使用掛鉤,一行代碼:

git --git-dir=. --work-tree=$PWD/.. reset --hard 

爲了更加精確,編輯服務器上的文件.git/hooks/post-receive

#!/bin/sh 
git --git-dir=. --work-tree=$PWD/.. reset --hard 

將其設置爲可執行:

chmod +x .git/hooks/post-receive 

當從客戶端推送到這個回購時,應該這樣說:

HEAD is now at abcd123 comment 
+1

在問題被提出之前,比改變環境更好,並且可以在git中使用。 – digenishjkl 2014-07-29 11:45:30

+1

應該是被接受的答案。 – sjy 2014-09-15 07:40:11