web-dev-qa-db-ja.com

git内のファイルへの特定の変更を無視しますが、ファイル全体は無視しません

ローカルで変更されたファイルをgitリポジトリに持っています。 gitにローカルの変更を永久に無視させたいが、ファイルは無視させたくない。特に、

  • この変更以外でファイルが変更されない場合は、git add .はステージングしないでください。
  • 同様に、git commit -aコミットしないでください。
  • ファイルに追加の変更を加える場合は、その変更をステージングしてコミットできるはずですが、無視している変更はnotでなければなりません上演され、コミットされました。

これを行う方法はありますか?いくつかの調査を行って、「汚れ/クリーンサイクル」について読みました。正しく読んだ場合、

  1. ファイルは変更されていないものとしてマークされ、
  2. チェックアウトすると、行った変更が上書きされます。
  3. そして、スクリプトが自動的に変更を再適用し、ファイルを再び未変更としてマークします。

私はgitとスクリプティングに非常に慣れていません(私はC#とJavaの経験がある)のインターンです)、それが私がする必要がある場合は、詳細な手順またはリンクを投稿してください汚れ/クリーンサイクルを設定する方法のチュートリアルに

Background:作業ブランチをトランクと同期させないようにしたい。優先度の低いバグがあり、開発マシンにのみ影響を与えるため、問題を修正するのではなく、問題のコードをコメント化しています。明らかに、このコードが正常に機能する本番環境から削除されることは望ましくありません。

45
Kevin

私が見ているように、あなたが説明している状況はこれです:ローカルリポジトリとは異なる作業ディレクトリを維持したいです。

これはお勧めできません。これらの変更はコミットされないので、ファイルが誤って削除されたり、意図しない方法で変更されたりした場合は、ほとんど頼ることができません。

したがって、実際にはすべての変更をコミットすることをお勧めします。これらの変更を分離する場合は、ブランチを使用して簡単に行うことができます。例

git checkout -b new-branch
# now you can change the file without affecting master
echo bar >> foo
git add
git commit
# and back to master
git checkout master
3
Steven Penny

skip-worktreeビットを使用できます。それをオンにします:

git update-index --skip-worktree <file>

その後、gitは<file>のローカル変更をステージングすることはなく、git自体が<file>に(たとえば、マージまたはチェックアウトで)書き込む必要がある場合、(大声で)失敗します。

今後の変更をステージングする場合は、オフにして新しい変更をステージングしてから、オンに戻すことができます。

git update-index --no-skip-worktree <file>
git add -p <file>
git update-index --skip-worktree <file>

完璧ではありませんが、これで十分かもしれません。 <file>に段階的な変更がないことに気づくのはあなた次第です。gitはもはやそれを教えないからです

注:私の最初の提案はassume-unchangedを使用することでした。 Git-'assume-unchanged'と 'skip-worktree'の違い で説明されているように、本当に必要なのはskip-worktreeです。特に、assume-unchangedはファイルを変更しないというGitへの約束であり、その約束に違反した場合、Gitは変更を消去またはコミットすることができます!対照的に、Gitはskip-worktreeの変更を消去またはコミットしません。

41
Mark Lodato

Gitの「パッチモード」は、ファイルから特定の変更のみをコミットに追加するのに最適です。

開始するには、git add -pgit commit -p(完了時にメッセージをコミットするためのストレート)、またはgit add --interactive(より多くのプロンプト)。

基本的に、git diffそして、ステージングするかどうかを尋ねます。

変更に達したら、n oまたはeと答えて、$ EDITORでパッチを開きます。

6
Riking

これらの回答は良いですが、@ Kevinの問題を最善に解決しない可能性があります。私も同様の懸念を抱き、設定ファイルを頻繁に編集して、作業中のアプリが本番のデータベースではなく自分のプライベート開発データベースにアクセスするようにしました。誤ってチェックインしてこれらの構成変更をプッシュするのは時間の問題です! 軽量ファイルを無視する方法が必要でした。これが私が学んだことです:

  • まず、必要な変更をファイルに加えます。 my_configと呼びます。

  • その変更のパッチファイルをgit diff >../somewhere-else/my_config.patchで作成します

  • ここでgitにそのファイルを無視するように指示します(チェックインされた.gitignoreを変更する必要はありません):git update-index --assume-unchanged my_config

さて、あなたがmy_configに変更を加えない限り、チェックインしたいdoなら、自由に作業できます。 my_configを無視しないようにするには、git update-index --no-assume-unchanged my_configを実行します。誰かがmy_configに加えた変更を取り込んだ後は、git apply ../somewhere-else/my_config.patchを使用してプライベートな変更を簡単に復元し、上記のように... assume-unchangedにして、作業に戻ることができます。

~/.gitconfigに入力できる便利なエイリアスは次のとおりです:

[alias]
    unchanged = update-index --assume-unchanged
    changed = update-index --no-assume-unchanged
    show-unchanged = !"git ls-files -v | sed -e 's/^[a-z] //p; d'"
6
Tyler Perkins

注:他の人々は、永続的なローカル変更を維持することは悪い考えであり、私が同意する理由はありません。他のオプションを検討してください。

ここに私が好きな方法があります:

  1. ローカルマシンに残しておきたい変更をいくつか加えます。
  2. 使用する git branch localおよびgit checkout localローカル変更のための新しいブランチを作成します。 (私が間違っていなければ、これらのコマンドはリモートブランチを自動的にセットアップしないため、新しいブランチはプッシュされません。)
  3. 使用する git commit変更をコミットします。
  4. アップストリームにプッシュする変更を行います。
  5. 使用する git checkout parentプッシュするブランチに戻ります。
  6. 使用する git commitこのブランチにコミットします。
  7. 使用する git Push to変更をプッシュします。
  8. 使用する git checkout localを使用してローカルブランチに戻ります。
  9. 使用する git rebase parent変更をparentからlocalに取り込みます。 rebaseを使用すると、ローカルの変更がparentの変更の上に留まるようになります。
  10. 手順4に戻り、吐き気を繰り返します。

これにより、ローカルでない変更を行うたびに、ローカルの変更とそうでない変更を手動でgitに指示する必要がなくなります。

2
Tanner Swett

はい、これはおそらく汚れ/クリーンフィルターを使用して行うことができます。ただし、これはかなり複雑でエラーが発生しやすいため、これを実行しないことを強くお勧めします(たとえば、gitで構築する多くのツールを混乱させ、デバッグが困難になるなど)。

また、通常、ローカルで永続的な変更を行うことはお勧めできません。 SCMを使用する際の重要なポイントの1つは、バージョンをチェックアウトしてすぐに機能させることができるということです。つまり、必要なものすべてをチェックインする必要があります。

私はこれを行うための「いい」方法はないと思います。gitでも、おそらく他のほとんどのSCMでも。要件を再検討することをお勧めします。

問題は、「混合コンテンツ」のファイルがあることです:常に同じであるコンテンツと、ローカルで変更する必要があるコンテンツ(マシン固有のオプション?)があります。これを処理するための推奨される方法は、問題のあるファイルをチェックインするのではなく、「テンプレート」ファイルをチェックインして、ビルド時に実際のファイルを生成することです。これを調べてみてください。現在は(おそらく)より多くの作業が必要になりますが、特により多くのバリエーションをサポートする必要がある場合や、他の人々が同じプロジェクトで作業したい場合は、物事が簡単になります。

編集(コメントの情報に基づく)

開発マシンにのみ必要で、本番環境では必要ないローカルコードの変更を無視するように記述します。

その場合、コメントアウトする代わりに、コードを何らかの条件でラップして、開発マシンでのみ実行されるようにします(例:条件付きコンパイルを使用するか、設定ファイルまたは環境プロパティを読み取るか、...(1 ))。その後、通常どおりコードをチェックインできます。

さらに、バグを修正するだけです。バグが開発を困難にする場合、私見はそれが優先度の高いものです。

コードをコメント化するだけではお勧めできません。エラーが発生しやすく、チェックアウトするたびに実行する必要があります。何よりも、開発と本番で異なるコードを実行すると問題が発生するため、可能な限り回避する必要があります。

(1)例として:当社では、このような場合のために特別に環境変数を用意しています。これは、コードが開発中、ベータテスト中、本番のどちらで実行されているかを示し、ビルドスクリプトとデプロイスクリプトによって設定されます。ただし、通常は、異なるファイルパスを選択するなどの単純な目的でのみ使用されます。上で説明したように、環境に基づいてプログラムロジックを変更することはお勧めしません。

1
sleske

(コメントにあるように)同じファイルを並行して変更する必要があるため.gitignoreを使用できない場合、1つのオプションはgit add -pです。これを使用して、適宜追加またはスキップできます。

ここで上記のgitコマンドを使用する際の問題は、手動のプロセスになることです。問題に対して他の自動化されたアプローチを見つけられないかもしれません。

0
Bijendra

IDEとしてintellijを使用している場合は、OPが要求することを正確に実行すると思われるきちんとした機能(変更リスト)があります。

ローカルの差分の特定の部分にマークを付けて名前を付けることができます。メモリが機能する場合、これにより、これらの変更が他のすべてのローカル変更から分離され、intellijからコミットを行う限り、積極的に行うことを選択した場合にのみ、コミットのためにステージングされます。

0
LOAS

Git 2.5(2015年7月)以降、 git worktree を使用できます。

git worktree add -b patch-1 ../patch-1

これは本質的にはブランチを作成するだけですが、新しいブランチを親リポジトリと一緒に新しいフォルダに入れます。コミットせずにこのブランチで作業でき、クリーンな作業ディレクトリでマスターに戻ることができるので、これは素晴らしいことです。

0
user4427511