gitは特定の行を無視できますか?


114

電話のネイティブブラウザでテストしているときに、gitを使用してphonegapに同期しています。そのため、次の行があります。

var isPhoneGap = false;

ビルド時に明らかにこれを変更しますが、この1行を無視するようにgitを設定する方法はありますか、それとも独自のファイルに入れて無視する必要がありますか?

OSX 10.6でGitxとターミナルを使用しています。


@ user494461:Gitフィルターがその方法です:stackoverflow.com/a/16244970/520162
eckes

1
環境を検出して環境設定ファイルを使用できませんか?
exussum 2014年

つまり、いいえ。ただし、コメント付きの特定のコードを探し、それをgitに公開する前に削除するプリプロセッサスクリプトを作成しました。こちらをご覧ください:github.com/franklinchou/ahk_config/blob/master/preprocess.sh
franklin

回答:


103

ファイルが特定のタイプである場合、ファイルで宣言できるコンテンツフィルタードライバーを宣言でき.gitattributesます(「Git属性」の「キーワード拡張」に示されています)。

http://git-scm.com/figures/18333fig0702-tn.png

*.yourType filter=yourFilterName

(必要に応じて、特定のファイルにそのフィルターを設定することもできます)

実装:

  • yourFilterName.smudge(でトリガーgit checkout)および

    git config --global filter.yourFilterName.smudge 'sed "s/isPhoneGap = .*/isPhoneGap = true/"'
    
  • yourFilterName.clean(でトリガーgit add

    git config --global filter.yourFilterName.clean 'sed "s/isPhoneGap = .*/isPhoneGap = false/"'
    

ファイルはで変更されずに表示されますがgit status、チェックアウトされたバージョンはの正しい値になりisPhoneGapます。


1
これをありがとう。うまくいきました。git diff or gitステータスを作成する方法を知っていますか?だから私はまだ何が違うのか見ることができますか?私の使用例はデバッグログ用です...最終的には削除したい... @jthill @VonC
timh

1
@timhフィルターが機能している場合、git statusまたはgit diffは何も表示しません。
VonC 2014年

1
GITでこれほど簡単な方法はないのは残念です。git ignore <filename> <linenumber>はとても便利です!
kiedysktos

22
@kiedysktos linenumber?行番号が変わった場合はどうなりますか?
VonC

これはうまく機能しましたが、Windowsユーザーは注意してください。gitconfigは保持する文字が非常にうるさいため、いくつかのエキゾチックな正規表現を試すと、問題が発生する可能性があります。sed-callsを、gitconfigから呼び出した別のhelper.shファイルに入れて、sedのsh ".git/helper.sh"パラメーターを確実に通過させました"$@"(ファイルパスだけが渡されたと想定しています)。
ohaal

43

使用できます

git update-index --assume-unchanged [file]

追跡したくない1つのファイルの変更を無視します。リポジトリにファイルが必要なときにこのソリューションを使用しますが、このファイルには変更が必要な部分があり、常に追跡する必要はありません。

ファイルに重要な変更がある場合、これを行う必要があります。

git update-index --no-assume-unchanged [file]

また、パラメーターについては、Git doc update-indexを参照して--[no-]assume-unchangedください。

これらのフラグを指定すると、パスに記録されたオブジェクト名は更新されません。代わりに、これらのオプションは、パスの「変更されていない」ビットを設定および設定解除します。「変更されていない」ビットがオンになっていると、gitは作業ツリーファイルの変更のチェックを停止するため、手動でビットの設定を解除して、作業ツリーファイルを変更したときにgitに通知する必要があります。


2
これを実行しても、git pullを実行しても新しいバージョンがフェッチされますか?
Saad Rehman Shah

1
@Caffeine git pullを実行すると、コミットされた最後のバージョンが取得されます。これは、ファイルを「--assume-unchanged」に変更する前の最後になります。
Carlos

1
私は--skip-worktreeほとんどの目的のためのより良いオプションだと思います。stackoverflow.com/a/39583010/4233593
Jeff Puckett


3
これは、特定の行ではなくファイル全体の更新を無視します
nikoss

6

Gitxを使用すると、個々の行をコミットまたは無視できます(既に知っている場合があります)が、コミットするたびにそうする必要があります。デプロイメントターゲットごとに構成ファイル(バージョンを付けることができます)と、サーバーを起動するためのいくつかのランタイムパラメーター(など./myserver --config=whatever.js)を用意する方が良いと思います。


5

https://stackoverflow.com/a/20574486/4935114を続けて、@ Mikeは、ステージングされたファイルで無視したい行のpre-commitフックを作成することを提案しましたgrep。フックはそれらの行がステージングされたかどうかをチェックします。もしそうなら、それはecho警告であり、それexitはコードである1ので、コミットプロセスは続行されません。

@Mike の回答に触発されて、私はおそらく、無視したい特定の行を自動的に reset-pフラグ付きで)sする、彼のフックの改良版を使用していることに気付きました。

このフックが無視されるこの行を持つ多くのファイルがある状況でこのフックが機能するかどうかはわかりませんが、このpre-commitフックは特定のファイルでこの行の変更を探しますbuildVars.java。私のマシンでテストしたとき、フックスクリプトは次のようになりました。

#!/bin/sh

# this hook looks for lines with the text `var isPhoneGap = false;` in the file `buildVars.java` and it resets these lines to the previous state before staged with `reset -p`

if [[ $(git diff --no-ext-diff --cached buildVars.java | grep --count -e "var\ isPhoneGap[\ ]*=[\ ]*") -ne 0 ]]; then
    cat <<EOW
WARNING: You are attempting to commit changes which are not supposed to be commited according to this \`pre-commit\` hook
This \`pre-commit\` hook will reset all the files containing this line to it's previous state in the last commit.
EOW
    echo /$'\n'isPhoneGap$'\n'y$'\n'q | git reset -p
    # BONUS: Check if after reseting, there is no actual changes to be commited and if so, exit 1 so the commit process will abort.
    if [[ $(git diff --no-ext-diff --cached | wc -l) -eq 0 ]]; then
        echo there are no actual changes to be commited and besides the change to the variable \'isPhoneGap\' so I won\'t commit.
        exit 1
    fi
fi

説明

私が行ったのはisPhoneGap、対話型resetプロセス中に正規表現を検索する制御シーケンスをエコーすることでした。このように押したユーザーエミュレーション/を検索するためにisPhoneGap、プレスy彼はこのパッチを破棄したい、最後に押したかどうかを尋ねられたときq、対話型を終了することをreset

インタラクティブなリバースパッチプロセスについては、https//git-scm.com/docs/git-add#git-add-patchで説明されています


注:上記のスクリプトは、変数interactive.singleKeyがであることを前提としていますfalse。をに設定した場合は、警告の直後にコマンドからtrue削除してください。$'\n'echo


3

これは、gitフィルターで実行できる方法です。

  1. gitattributesファイルを作成/開く:
    • <プロジェクトルート> /。gitattributes(リポジトリにコミットされます)
      または
    • <プロジェクトルート> /。git / info / attributes(リポジトリにコミットされません)
  2. フィルタリングするファイルを定義する行を追加します。
    • *.rb filter=gitignore、つまりgitignoreすべての*.rbファイルで指定されたフィルターを実行
  3. gitignoreフィルターを定義しますgitconfig
    • $ git config --global filter.gitignore.clean "sed '/#gitignore$/'d"、つまりこれらの行を削除します
    • $ git config --global filter.gitignore.smudge cat、つまり、リポジトリからファイルをプルするときに何もしない

注:
もちろん、これは、行がで終わるとき#gitignoreに適用され、グローバルにに適用されるルビーファイル用です~/.gitconfig。ただし、目的に応じてこれを変更してください。

警告!!
これにより、作業ファイルが(もちろん)リポジトリとは異なります。チェックアウトまたはリベースすると、これらの行が失われます。これらの行はチェックアウト、リベース、またはプルで繰り返し失われるため、このトリックは役に立たないように見えるかもしれませんが、私はそれを利用するために特定のユースケースを持っています。

ただ、git stash save "proj1-debug" フィルタがアクティブである間(ちょうど一時的にそれを無効にするgitconfigか何か)。このようにしてgit stash apply、これらの行が誤ってコミットされることを恐れずに、いつでもデバッグコードをいつでもコードに適用できます。

これらの問題に対処するための考えられるアイデアはありますが、別の機会に実装してみます。

gitフィルターとgitattributesについて言及してくれたRudiとjw013に感謝します。


2

コンテンツフィルタードライバーは適切なソリューションではありません。この行をgit status/ etc から隠すことができるかもしれませんが、実際には無視されていません。値を変更すると、変更が表示されない場合でも、作業ディレクトリはダーティとマークされます。

この行をバージョン管理の対象から外したい場合は、コマンドライン引数に変更するか、無視されたインクルードファイルまたはビルドファイルに配置することが唯一の実用的な方法です。


「値を変更するとすぐに、変更が表示されない場合でも作業ディレクトリがダーティとマークされます」:クリーンスクリプトがファイルを元のコンテンツに復元する場合は、そうならないはずです。
VonC、2014年

それは私が思っていたものです。私はGitExtensionsを使用していますが、差分ペインが空白であってもファイルが変更されたものとして表示されます。おそらく、ファイルのチェックインまでクリーンフィルターが実行されないためです。おそらくgit-gitではなくmsysgitだからです。IDK、YMMV
patricktokeeffe

1

これは、ソースの複数行で発生する可能性があるものだと思います。

含めるだけのデフォルトの.userbuildconfigファイルを用意し、デフォルトをチェックインするのが最もクリーンだと思います。次に、Carlosの提案を使用て、そのファイルのみを変更されないと見なすようにマークできます。このようにして、設定を確認する必要があるファイルへの他の変更を見逃すことはありません。

これにより、ローカルでプリプロセッサマクロを調整できます(または、Javaの場合は、このようなhttps://stackoverflow.com/a/1813873/1270965)。


-1

いいえ。.gitignoreの行はファイル名ではなくファイルの内容と一致するため、無視できるのは個々のファイル(およびそれ以上)だけです。これに対する解決策についてはすでに説明しました。つまり、無視するコンテンツを含む単一のファイルを無視します。


私の場合、無視されたファイルのコンテンツを含めるだけで十分であり、可能であることに同意します。したがって、無視できるすべての設定を移動します。そこ。また、無視されたファイルのコピーを作成し、それを参照としてインデックスに追加したので、そのファイルの内容に関する情報が失われることはありません。
Urs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.