15

プッシュしているリモートレポにポストレシーブフックスクリプトがあります。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にあると言っていますが、サーバーにログインすると、リモートの作業コピーがまったく更新されないということです!

何か案が?

4

3 に答える 3

25

問題は、フック スクリプト用に作成された環境と通常の環境での Git コマンドの動作の違いです。

まず、フック スクリプトは、現在の作業ディレクトリを Git ディレクトリ自体 (つまり、.git/ベア リポジトリ以外のディレクトリ) に設定して実行します。次に、GIT_DIR 環境変数が設定され、Git リポジトリ (ここでも.git/非ベア リポジトリのディレクトリ) を指すフック スクリプトが実行されます。

git reset --hard通常、ディレクトリから実行しようと.git/すると、次のメッセージが表示されて終了します。

fatal: This operation must be run in a work tree

しかし、GIT_DIR が設定されている場合、Git コマンドは現在のディレクトリが作業ツリーであると想定します。フックが実行されるときの現在のディレクトリは.git/ディレクトリであるため、実際には作業ツリー ファイルを親ディレクトリではなくgit reset --hard直接「チェックアウト」しています(つまり、バージョン管理されたコンテンツのコピーがディレクトリにあります)。.git/.git/

Git が Git リポジトリ自体で使用するパス名と一致するパス名が、リポジトリ内のバージョン管理されたコンテンツにないことを願っています。それらが一致する場合git reset --hardは、リポジトリの内部構造の一部が上書きされているため、おそらく他のリポジトリから再クローンする必要があります。バージョン管理されたコンテンツのいずれも Git の内部パス名と競合しないと確信している場合は、次の方法でクリーンアップできる可能性があります。

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

これにより、現在追跡されているファイルのみが削除されます (その後削除されたが、壊れたフックがアクティブな間にプッシュされたヒントコミットで一度追跡されたファイルが残ります)。


1 つの解決策は、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 「「git push」後にリモート リポジトリに変更が表示されないのはなぜですか?」</a> では、これを行う更新後スクリプトを推奨しています。リンクされたスクリプトは、ハード リセットを実行する前にインデックスまたは作業ツリーが汚れている場合にスタッシュを作成するため、はるかに安全です。

于 2011-04-04T04:11:01.893 に答える
17

In short, use the hook one-liner:

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

To be more precise, edit the file .git/hooks/post-receive on the server:

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

Set it executable:

chmod +x .git/hooks/post-receive

When pushing to this repo from the client, it should say something like:

HEAD is now at abcd123 comment
于 2012-11-21T10:17:46.143 に答える
0

スクリプトはおそらく実行されません。ダムの http サーバーでは実行されません。ssh で実行されます。スマートhttpサーバーについてはわかりません。

そうでない場合は、フックの「実行」許可を確認する必要があります (chmod +x .git/hooks/post-receive)。その間、一般的に所有権と権限を確認してください。

これで問題ないと思われる場合は、ログステートメントをスクリプトの最初の行として含め (例: date "%T $0 executed" >> /tmp/debug_hook.log)、ログファイルをチェックして何かが更新されたかどうかを確認します。

また、プッシュが実際には何もしない(すべてが最新の状態になる) 可能性もあります。その場合、フックが呼び出されないのは理にかなっています

これでヒントが得られない場合は、.git/config がサーバー上 (または少なくともその一部) にあるので投稿してください。git log -1 HEADサーバーで期待される結果が得られますか? フック スクリプトには、GIT_DIR、GIT_WORK_TREE、または GIT_INDEX_FILE をオーバーライドする可能性のあるものが含まれていますか?

于 2011-04-03T23:31:35.183 に答える