40

ファイルを使用できない場合があり.gitignoreます。それ以外の場合はgit push、重要なファイルがリモートからパージされます。git update-index --assume-unchanged <file>このような場合、無視したいファイルに適用します。

変更されていないと仮定するルールを適用して を呼び出したgit push後、これらのルールはリモート ブランチにアタッチされ、(他のクライアントからの) 以降のすべてのプルでルールが継承されるようになりますか? それとも、これらのクライアントもgit update-index --assume-unchanged <file>マシンで個別にコマンドを実行する必要がありますか?

コマンドが継承されていない場合 -- 以前にこのためのサーバー フックを作成した人はいますか? 現在および将来のすべてのクライアントがそれに対して保護することを義務付ける代わりに?

4

3 に答える 3

56

インデックスはワークステーションに対してローカルであり、そこに加えた変更は同じリモートの他のクローンには反映されません。

(質問が更新された後、更新されました)

.gitignore ファイル

.gitignore ファイルを使用できない場合があります。そうしないと、git push 時に重要なファイルがリモートから削除されます。

本当じゃない。git ignore ファイルは、リポジトリで既に追跡されているファイルには影響しません。コミット後にファイルを追加すると、そのファイル.gitignoreはリポジトリ内に残ります。パージされません。実際、まったく無視されていないかのように振る舞います。

これは、一時リポジトリで簡単に確認できます。

$ mkdir -p /tmp/repo
$ cd /tmp/repo
$ git init
Initialized empty Git repository in /tmp/repo/.git/
$ echo red > a.txt
$ git commit -am '1'
 1 file changed, 1 insertion(+)
 create mode 100644 a.txt
$ echo a.txt > .gitignore
$ echo b.txt >> .gitignore
$ git commit -am '2'
 1 file changed, 2 insertions(+)
 create mode 100644 .gitignore

リポジトリには と の 2 つのファイルが含まれるようにa.txtなり.gitignoreました。どちらも正常に動作し、クローンを作成すると確認できます。

$ cd ..
$ git clone file://repo repo2
$ ls -A repo2
.git       .gitignore a.txt
$ cd repo

無視されたファイルと request の両方を変更すると、gitignor されているにもかかわらず、変更されたものとしてgit status表示されます。a.txt通常どおり追加してコミットできます。実際、追跡対象のファイルを gitignore に追加すると、まったく gitignore に存在しないかのように動作します。

$ echo green > a.txt
$ echo blue > b.txt
$ git status --short
 M a.txt
$ git add a.txt

git が追跡を開始する前に無視されたため、b.txtファイルは異なります。通常、このファイルはリポジトリに作成されませんが、必要に応じて強制的に作成できます。

$ git add b.txt
The following paths are ignored by one of your .gitignore files:
b.txt
Use -f if you really want to add them.
fatal: no files added
$ git add -f b.txt

発行git commitすると、両方とも git が無視された 2 つのファイルがコミットされるようになりました。

$ git commit -m '3'
 2 files changed, 1 insertion(+), 1 deletion(-)
 create mode 100644 b.txt

簡単に言うと、git ignore ルールをガイドラインと考えてください :-)

仮定不変の伝播

変更されていないと仮定するルールを適用して git push を呼び出した後、これらのルールはリモート ブランチにアタッチされ、(他のクライアントからの) 以降のすべてのプルでルールが継承されるようになりますか? それとも、これらのクライアントもマシンで git update-index --assume-unchanged コマンドを個別に実行する必要がありますか?

後者。あなたが得ることができる最も近いものは、あなたのために変更を加えるシェルスクリプトをリポジトリに追加することです.

サーバーフック?

コマンドが継承されていない場合 -- 以前にこのためのサーバー フックを作成した人はいますか? 現在および将来のすべてのクライアントがそれに対して保護することを義務付ける代わりに?

重要なファイルがプッシュの一部ではないかのように削除するサーバー フックを作成することが目的の場合、それは不可能です。Git push は主にcommit オブジェクト(およびrefs ) を扱います。ツリーやブロブなどの依存オブジェクトは、コミットからの到達可能性に従って、必要に応じて転送されます。つまり、コミットされていない場合、リモートにプッシュすることはできません (これは単純化しすぎていますが、リポジトリ内のファイルにも当てはまります)。さらに、git コミットは暗号で保護されています。コミット ハッシュを変更せずにコミットを変更することはできません。コミット ハッシュを変更すると、基本的に別の新しいコミットが作成されます (古いコミットと同じ差分が発生する可能性があります)。

これは、サーバーがコミットを書き換えることができないことを意味します。少なくとも、プッシュを行ったクライアントを深刻に混乱させることなくではありません (古いコミット オブジェクトのコピーがまだ残っています)。

できることは、更新したくないファイルがコミットに含まれている場合にコミットを拒否する post-receive フックを作成することです。git commit --assume-unchanged同僚に説明するのが難しい場合、望ましくないファイルが含まれていない状態でコミットを再作成するために対話型リベースを使用する方法を同僚に説明するのがさらに困難になる可能性があるため、これでは問題は実際には解決されません。

簡単に言えば、今のように、一度コミットしてから決してコミットする必要がないファイルを扱っている場合は、すべての人を想定して変更されていない (おそらく post-receive フックと組み合わせて) を使用し続けることは、最も悪い選択ではないと思います。

考えられる回避策

これらのファイル全体を git から遠ざけることができれば、あなたの生活はずっと楽になります。私が考えることができることの1つ:

  • リポジトリ内のファイルを lib ディレクトリに移動します。常に変更されることはありません。
  • .gitignoreファイルは最終的な場所にあり、必要な場所に常に不要な変更が加えられます
  • クローン作成後、作業を​​開始する前に一度実行する必要がある「init」スクリプトをリポジトリに追加します。このスクリプトは、ファイルを適切な場所にコピーします。
于 2013-09-02T10:58:33.273 に答える
1

考えられる解決策の 1 つは、クライアント側のフックを作成して、無視したいファイルにローカルの変更がコミットされないようにすることです。

これらのフックは、コミット前、コミット後、プッシュ前など、git の特定のイベントで実行されるスクリプトです。サンプルは<your_repo>/.git/hooks/.

悪いニュースは、それらもバージョン管理されていないことです。そのため、独自のセットアップ スクリプトを作成して、フック スクリプトを にコピーする必要があります.git/hooks/

以下は、ファイルがコミットされるのを防ぐ pre-commit フックの小さなサンプルですforbidden.txt(ファイルのリストを取得するように適合させることができます)。

ROOT_DIR="$(pwd)/"
LIST=$(git diff --cached --name-only --diff-filter=ACRM)

for file in $LIST
do
    if [ "$file" == “forbidden.txt” ]; then
        echo You cannot commit file $file. Please reset it and try again.
        exit 1
    fi
done
exit 0
于 2017-07-18T05:40:17.510 に答える