Git-'assume-unchanged'と 'skip-worktree'の違い


450

リポジトリにコミットしたくないファイルへのローカル変更があります。サーバー上でアプリケーションを構築するための設定ファイルですが、異なる設定でローカルに構築したいのですが。当然、ステージング対象として「git status」を実行すると、ファイルは常に表示されます。この特定の変更を非表示にして、コミットしません。ファイルに他の変更を加えません。

少し調べてみると、「仮定-変更なし」と「スキップワークツリー」の2つのオプションが表示されます。ここでの前の質問はそれらについて話しますが、実際にはそれらの違いを説明しません。私の質問はこれです:2つのコマンドはどのように違うのですか?なぜ誰かがどちらか一方を使用するのですか?


1
通常、私は.gitignore同様の目的で使用しています。このソリューションはあなたのために機能しますか?
samuil 2012年

45
samuil、.gitignoreは、変更ではなく追加を無視します。ファイルがすでにgitにある場合、それが.gitignoreにリストされている場合はイベントが追跡されます
Grigory

ここで説明されているように「リフレッシュ」するために、すべてを削除してすべてを追加することはできませんか?stackoverflow.com/questions/7075923/…@Grigory
Daniel Springer

2
OPの意図を正しく理解していれば、このファイルは無視すべきではありません。ファイルはリポジトリにある必要がありますが、彼が行ったこれらの非常に具体的な変更はコミットしないでください。
Simone

回答:


666

あなたが欲しいskip-worktree

assume-unchangedファイルのグループが変更されているかどうかを確認するのに費用がかかる場合のために設計されています。ビットを設定すると、git(もちろん)インデックスのその部分に対応するファイルが作業コピーで変更されていないと想定します。そのため、stat呼び出しの混乱を回避できます。このビットは、インデックス内のファイルのエントリが変更されるたびに(したがって、ファイルが上流で変更されるときに)失われます。

skip-worktreeそれだけではありません。ファイルが変更されている(またはファイルなどで変更する必要がある)ことがgit わかっている場合でも、reset --hard代わりにインデックスのバージョンを使用して、ファイルが変更されていないふりをします。これは、インデックスが破棄されるまで続きます。

この違いによる影響と一般的な使用例については、http//fallengamer.livejournal.com/93321.htmlに要約があります。

その記事から:

  • --assume-unchanged開発者ファイルを変更してはならないと想定しています。このフラグは、SDKなどの変更されないフォルダーのパフォーマンス向上させるためのものです。
  • --skip-worktree開発者変更する必要があるため、特定のファイルに触れないようにgitに指示する場合に便利です。たとえば、メインリポジトリのアップストリームが本番環境対応の構成ファイルをホストしていて、それらのファイルへの変更を誤ってコミットしたくない場合は、--skip-worktreeまさにそれが必要です。

3
それは理にかなっている。skip-worktreeは確かに進むべき道のようです。ありがとう!
ckb

100
数秒の検索と読み取りを節約するための小さなメモ。--skip-worktreeエフェクトをキャンセルしてフラグの設定を解除するには、--no-skip-worktreeオプションがあります。まったく同じように機能します。これは、手がずれて間違ったファイルにフラグが付けられた場合、または状況が変更され、以前にスキップされたファイルが無視されなくなった場合に役立ちます。
drdaeman 2015

18
上記の私自身の質問に答えるために--skip-worktree、と.git/info/excludeファイルの違いは、前者は現在追跡されているファイルに対しても機能することです。.git/info/excludeのように.gitignore、追跡されていないファイルを誤ってインデックスに追加するのを防ぐだけで、すでに追跡されているファイルに変更を加えることはできません。
LinusR 2015年

13
これをリモートにプッシュして、すべてのクローンで保持できますか?
CMCDragonkai 2016年

4
ただの使い方git update-index --skip-worktree <file_name>
奥様

108

注:fallengamerは2011年にいくつかのテストを行ったため(それらは古くなっている可能性があります)、彼の調査結果は次のとおりです。

オペレーション

  • ファイルがローカルリポジトリと上流の両方に変更された
    git pull
    Gitはとにかくローカルの変更を保存します。
    したがって、フラグのいずれかでマークしたデータを誤って失うことはありません。
    • assume-unchangedフラグ付きファイル:Gitはローカルファイルを上書きしません。代わりに、それは競合を出力し、それらを解決する方法をアドバイスします
    • skip-worktreeフラグ付きファイル:Gitはローカルファイルを上書きしません。代わりに、それは競合を出力し、それらを解決する方法をアドバイスします

  • ファイルがローカルリポジトリの両方を変更し、上流、とにかくプルしようとしている 使用していくつかの余分な手作業で結果をしかし、あなたは任意のローカルな変更があった場合は、少なくともあなたは、任意のデータを失うことはありません。
    git stash
    git pull
    skip-worktree
    • assume-unchangedフラグ付きファイル:ローカルの変更をすべて破棄し、復元することはできません。効果は「git reset --hard」のようなものです。' git pull'呼び出しは成功します
    • skip-worktreeフラグ付きのファイル:Stashはファイルで機能しませんでしたskip-worktree。' git pull'は上記と同じエラーで失敗します。開発者は手動でskip-worktreeフラグをリセットして、失敗を隠して完了できるようにする必要がありpullます。

  • ローカルでの変更なし、アップストリームファイルの変更 どちらのフラグでも、アップストリームの変更を取得できます。Gitは、あなたが約束を破ったことを検出し、フラグをリセットすることによって現実を反映することを選択しました。
    git pull
    assume-unchanged
    • assume-unchangedフラグ付きのファイル:コンテンツが更新され、フラグは失われます。
      ' git ls-files -v'は、フラグがH(からh)に変更されていることを示します。
    • skip-worktreeフラグ付きのファイル:コンテンツが更新され、フラグは保持されます。
      ' git ls-files -v'はS以前と同じフラグを表示しpullます。

  • ローカルファイルが変更された場合、 Gitはファイルに触れず、ファイルの現実(変更されないと約束されたファイルが変更された)を反映します。
    git reset --hard
    skip-worktreeassume-unchanged
    • assume-unchangedフラグ付きのファイル:ファイルの内容が元に戻されました。フラグはH(からh)にリセットされます。
    • skip-worktreeフラグ付きのファイル:ファイルの内容はそのままです。フラグは同じままです。

彼は次の分析を追加します:

  • ローカルデータを保存するために非常に懸命に努力しているようskip-worktreeです。しかし、それが安全であれば、上流の変更を取得することを妨げません。さらに、gitはのフラグをリセットしません。しかし、「」コマンドを無視すると、開発者にとって厄介な驚きなる可能性があります。pull
    reset --hard

  • Assume-unchangedフラグはpull操作で失われる可能性があり、そのようなファイル内のローカル変更はgitにとって重要ではないようです。

見る:

彼は結論付けている:

実際、どちらのフラグも十分に直感的ではありません

  • assume-unchanged開発者がファイルを変更してはならないと想定しています。ファイルが変更された場合–その変更は重要ではありません。このフラグは、SDKなどの変更されないフォルダーのパフォーマンスを向上させるためのものです。
    しかし、約束が破られてファイルが実際に変更された場合、gitはフラグを元に戻して現実を反映します。おそらく、通常は変更する必要のないフォルダーに一貫性のないフラグをいくつか設定しても問題ありません。

  • 一方skip-worktree、特定のファイルに触れないようにgitに指示する場合に便利です。これは、すでに追跡されている構成ファイルに役立ちます。
    アップストリームのメインリポジトリは本番環境に対応した構成をホストしますが、構成の一部の設定を変更してローカルテストを実行できます。また、このようなファイルの変更を誤ってチェックして、本番構成に影響を与えたくありません。その場合skip-worktreeは完璧なシーンになります。


Git 2.25.1(2020年2月)では、上記の「実際にはどちらのフラグも十分直感的ではない」ことがさらに明確にされています。

コミット7a2dc95コミット1b13e90(2020年1月22日)を参照してください。カールソン(bk2204
(合併によりJunio C浜野- gitster-53a8329コミットし、2020年1月30日)を
Gitのメーリングリスト

doc:ユーザーが追跡されたファイルを無視しようとしないようにします

サインオフ:ジェフキング
サインオフ:ブライアンm。カールソン

ユーザーがGitが追跡するファイルへの変更を無視することはよくあることです。

この場合の一般的なシナリオは、IDE設定と構成ファイルです。これらは通常、追跡されるべきではなく、テンプレートメカニズムを使用して追跡されたファイルから生成される可能性があります。

ただし、ユーザーは想定されていない変更されていないワークツリービットについて学び、それを使用してこれを実行しようとします。

これらのビットが設定されている場合、多くの操作はユーザーの期待どおりに動作するため、これには問題がありますが、通常git checkout、ファイルを置き換える必要がある場合は操作が役立ちません。

この場合、特定の構成ファイルなどのデータが貴重な場合があり、ユーザーが破棄しても問題のないデータである場合があるため、この場合は適切な動作はありません。

これはサポートされている構成ではなく、ユーザーは既存の機能を意図しない目的で誤用し、一般的な悲しみと混乱を招く傾向があるgit update-indexため、ユーザーが代替ソリューションを探索する必要があることをユーザーに知らせるために、既存の動作とドキュメントの落とし穴を文書化しましょう。

さらに、構成ファイルの一般的なケースに対処するための推奨ソリューションを提供しましょう。これは、多くの環境でうまく使用されている既知のアプローチがあるためです。

git update-indexmanページには今含まれています:

ユーザーは、assume-unchangedskip-worktreeビットを使用して、追跡されているファイルへの変更を無視するようにGitに指示することをよく試みます。Gitは特定の操作を実行するときにインデックスに対して作業ツリーファイルを引き続きチェックする可能性があるため、これは期待どおりに機能しません。一般に、Gitは追跡されたファイルへの変更を無視する方法を提供しないため、代替ソリューションが推奨されます。

たとえば、変更するファイルがなんらかの構成ファイルである場合、リポジトリにはサンプルの構成ファイルを含めることができます。この構成ファイルは、無視された名前にコピーして変更できます。リポジトリには、サンプルファイルをテンプレートとして扱い、変更して自動的にコピーするスクリプトを含めることもできます。

最後の部分は、私がsmudge / cleanスクリプトに基づいた典型的なコンテンツフィルタードライバーを説明するものです。


7
git-statusでファイルが変更されたと報告されていなくても、ファイルにスキップワークツリーがあり、アップストリームが変更されている場合、プルしようとすると「commitまたはstashしてください」が表示されます。どうすればこれを回避できるので、人々がオリジンのプロダクション設定をいじくり回している間、ローカルの変更を維持できますか?
GreenAsJade 2014

3
はい、そうです。つまり、元のファイルとは異なる方法で維持したいだけのローカルファイルを作成するのは依然として非常に困難です。
GreenAsJade 14

1
@GreenAsJadeは古代のようです。2.2.xでテストできる可能性はありますか?
VonC、2014

1
@VonC、「Junioのコメント」へのリンクは変更履歴にありません。これはあなたが言っていたものですか?
マイケル-クレイシャーキーはどこですか2017年

1
@マイケルグッドキャッチ、ありがとう。私はそのリンクを答えに戻しました。
VonC 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.