22

汚れ/きれいなフィルターに関連する多くの関連する質問があります-私はそれらを読んで、さまざまなオプションを試してみましたが、まだ失敗しています. 自分に合った答えが得られるように質問できればと思います。

具体的には、これらの回答のほとんどが次のページにリンクしているページを読みました。


tl;dr

詳細な質問ですが、要約は次のとおりです。

  • スマッジ/クリーン フィルタを使用してファイルを管理するために、DEBUG = falseあるブランチのファイルと別のブランチにファイルを保存できますか? DEBUG = trueそしてどうやって?

バックグラウンド

bitbucket でホストされているさまざまなリモート リポジトリがあります。リモートリポジトリをラップトップに複製するために、Win8でSourceTreeを使用しています。開発、機能、リリースなどのためにさまざまなブランチを作成します (良くも悪くも成功した Git ブランチ モデルに従います)。

Dbug.javaコード内のさまざまなデバッグログ、モックなどの機能をオン/オフするブール値を含むAndroid Java クラスがあります。

public static final boolean DEBUG = false;

この値をfalse「本番」(マスター) ブランチにtrue置き、フィーチャー ブランチに置きたいと思います。

  • これはフィルターを使用して可能ですか、それともユースケースをすでに誤解していますか?
  • ローカルでホストされている同じリポジトリの 2 つのブランチ間でフィルターがこのように機能するのか、それともフィルターが 2 つのリポジトリ間でのみ機能するのかはわかりません。

フィルターの作成

ローカルで作業し、プロダクション ブランチを調べました。debug_flag.txt次の内容で呼び出されるテスト ファイルを作成しました。

// false on production branch
// true on other branches
DEBUG = false;

というローカル リポジトリのルートにファイルを作成し、.gitattributesそれにフィルター参照を追加しました。

debug_flag.txt filter=debug_on_off

.git/configフィルター定義でファイルを更新しました。

[filter "debug_on_off"]
    clean = sed -e 's/DEBUG = true/DEBUG = false/'
    smudge = sed -s 's/DEBUG = false/DEBUG = true/'
  • 私の理解では、これにより、本番環境では常にファイルの値が false になるはずですが、本番環境から分岐すると true の値になります。
  • これは正しい理解ですか?

フィルタのテスト

test以下を使用して新しいブランチを作成しました。

git checkout -b test

ファイルの内容を確認しました:

$ cat debug_flag.txt

// false on production branch
// true on other branches
DEBUG = false;
  • trueファイルに値が表示されることを期待していました
  • ファイルをチェックアウトしたときに「汚れ」フィルターが実行されているはずではありませんか?

ファイルに新しい行を追加し、コミットしました。その後、本番ブランチに戻りましたが、ここで奇妙なことが起こりました。

SourceTree でファイルを見ると、このブランチは作成されてから変更されていません。唯一の変更は別のブランチで行われたため、それは私が期待することです。

ターミナルまたは Notepad++ でファイルを見ると、値が変更されていることがわかります。

$ cat debug_flag.txt

// false on production branch
// true on other branches
DEBUG = true;

私はまだテスト ブランチから変更をマージしていません。プロダクション ブランチでコミットしていませんが、ファイルが変更されています

  • このブランチ内のファイルに対してスマッジ フィルタが実行されたようですが、ブランチ間では実行されませんでした。

パズルの重要なピースが欠けています。できれば、これを行った経験のある人が見つけられる単純なものであることを願っています。

私の賭けは、これは概念の単純な誤解です。

欠落している情報がある場合は、プロンプトを表示してください...


VonC の返信に基づく更新

基本的なフィルターの設定は非常にうまくいきました。configファイル内のフィルターを次のように定義しました。

[filter "debug_on_off"]
    clean = sed -e 's/DEBUG = true/DEBUG = false/'
    smudge = sed -s 's/DEBUG = false/DEBUG = true/'

新しいブランチを作成すると false -> true が修正され、マージ バックすると true -> false に変更されます。

変更を本番 (マスター) ブランチだけに限定するには、実行元のブランチを認識するカスタム スクリプトが必要でした。したがって、configファイルは次のようになりました。

[filter "debug_on_off"]
    clean = ./scripts/master_clean.sh
    smudge = ./scripts/master_smudge.sh

master_clean.sh:

#!/bin/sh
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
if [ "master" = "$branch" ]; then
    sed -e s/DEBUG = true/DEBUG = false/ $1
else
    cat $1
fi

master_smudge.sh:

#!/bin/sh
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
if [ "master" = "$branch" ]; then
    sed -e s/DEBUG = false/DEBUG = true/ $1
else
    cat $1
fi

この時点で、デバッグ ファイルの内容について、SourceTree で表示されているものと Notepad++ で表示されているものとの間に矛盾が生じています。SourceTree には変更が表示されていますが、Notepad++ には表示されていません。

私が提起した基本的な質問に答えているので、VonCの答えを受け入れています。

ただし、解決しようとしている根本的な問題を (私にとっては) 簡単な方法で解決するため、私が書いたソリューションを実装する可能性があります: 別のブランチに別の構成ファイルを保持します。

4

5 に答える 5

9

ファイルに値 true が表示されることを期待していました

コンテンツをチェックアウトせずに、新しいブランチを作成しただけです (そのコンテンツは、あなたがいたブランチと同じであるため)

汚れを強制的に実行するには、レポの上部で次のようにします。

git checkout HEAD --

テスト ブランチの変更をまだマージしておらず、プロダクション ブランチでコミットしていませんが、ファイルは変更されています。

これがコンテンツ フィルタ ドライバの考え方です。影響を与えずにコンテンツを変更しgit statusます (変更されたファイルは「未変更」として報告されます)。

ブランチごとにスマッジの動作を変えるには、現在のブランチの名前を調べることから始まるスクリプトを呼び出すことをお勧めします。
私の古い回答「ベスト プラクティス - Git + ビルドの自動化 - 設定を分離する」の例を参照してください。

#!/bin/sh
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
于 2014-04-07T10:41:42.053 に答える
3

VonCのアドバイスは、私が提起した正確な質問に対処していますが、最終的な詳細を解決することはできませんでした(質問の更新に従って)。この回答は、私がどのように物事を行ったかの詳細を示しています。


アップデート

以下の方法は、最初のマージで機能しました。しかし、その後は機能しなくなりました。それは私の調査の現在の状態を表しているので、ここに残しておきます。

マージ ドライバーが呼び出されなくなったようです。

また、以下に示す代わりに、、、またはカスタム スクリプト マージ ドライバー ( https://stackoverflow.com/a/930495/383414exit 0 ) を使用して、関連する質問からさまざまな変更を試みました。touch %Atrue


カスタム戦略を使用して根本的な問題を解決する回避策を見つけました。merge

  • ビルド ブランチのビルド ファイルを常にすべてのデバッグ値をオフに設定したいと考えています。
  • これにより、モック設定、ローカルホスト設定、ログがオンになっている製品の偶発的なリリースが防止されます。

この質問からの情報に基づいて、次の情報に基づいています: .gitattributes & ファイルの個々のマージ戦略

.git/config1) 次のように、ファイルにカスタム マージ ドライバを定義します。

[merge "ours"]
    name = "Keep ours merge"
    driver = true

この手順が必要かどうかはわかりませんが、一部の (古い?) システムのバグの回避策のようです。

(詳細: https://stackoverflow.com/a/13000959/383414 )

2) build/production/pristine ブランチにファイルを設定し.gitattributesて、特別なデバッグ フラグが上記のマージ戦略を使用するようにします。

私の質問のファイルを使用して、「運用」ブランチに移動し、次の行を.gitattributesファイルに追加します。

debug_flag.txt merge=ours

マージが「production」ブランチに戻されるたびに、git は「ours」として定義されたマージ戦略を探し、debug_flag.txt が上書きされるのを防ぎます。

3) 他のブランチでは、.gitattributesそのカスタム マージ戦略を使用せずにファイルを設定します。

4) 構成プロセスの最後の (しかし重要な) ステップは、すべてのブランチで debug_flag.txt ファイルを正しくセットアップし、各ブランチに変更をコミットすることです。

これで 2 つのブランチができ、それぞれに異なるバージョンの.gitattributes& debug_flag.txt ファイルが含まれているはずです。これにより、マージするたびに競合が発生することが保証されます。

競合がなければ、カスタムの "ours" マージ戦略は呼び出されず、ファイルが上書きされる可能性があります。

(詳細: https://stackoverflow.com/a/16739788/383414 )

5) 最後に、新しいブランチを "production" にマージします。手順 3 と 4 により、マージの競合が発生します。競合を解決して、2 つのブランチが相違点を保持するようにします。変更をコミットします。

これら 2 つのブランチ間の将来のマージはすべて、debug_flag.txt ファイルをシームレスに無視します。


これにより、異なるブランチに 2 つの異なる構成ファイルを持つという目標が達成されるため、デバッグを本番コードなどから簡単に分離できます。これは一般的な使用例のようで、このフォーラムで多くの関連する質問が寄せられていますが、それでも数時間かかりました。それを正しくするのに何日もかかります。

于 2014-04-07T13:37:23.603 に答える
3

expandrを見てください。これは、smudge/clean を使用して、さまざまなブランチにさまざまな構成をセットアップできるスクリプトです。基本的に、あなたが最初に求めていたものだけです。

現時点で最大の落とし穴は、ブランチを切り替えた後git checkout HEAD -- "$(git rev-parse --show-toplevel)"、作業ディレクトリを正しく汚すために a を実行する必要があることです。ただし、正常に動作するように見える場合もあります。理由はまだわかりません。「マージ再正規化」がオンになっていることが原因で、問題が発生しているのではないでしょうか。わからない。(私はそれを持っています。)

merge=oursもう1つの落とし穴は、各ブランチの .gitattributes ファイル自体を保護する必要があることです.gitattributes merge=ours。ここでの落とし穴は、個別のブランチを作成した後、各 .gitattributes ファイルに移動して、それぞれを変更する必要があることです (コメントを追加することをお勧めします#touched for merge=ours on master,#touched for merge=ours on test branchなど. これを行う必要があるmerge=oursのは、ファイルが受信ブランチとその親ブランチの両方でブランチの作成後に変更された場合にのみ、ファイルがマージで受信ブランチのバージョンに変更されないようにするためです。(git はファイルではなく、変更を扱うことを思い出してください。)

于 2014-09-15T23:24:14.940 に答える
0

最も簡単な解決策は、makefile を更新して、現在チェックアウトされているブランチのチェックを含めることです。ブランチが名前付きリストの一部である場合は、新しいビルド引数 -DDEBUG=true または -DDEBUG=false を定義します。

現在チェックアウトされている Git ブランチをプログラムで確認する方法を参照してください。

branch_name=$(git symbolic-ref -q HEAD)
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD}

PROD_BRANCHES := master \
                QA
debug_flag=
ifneq ($(filter $(branch_name),$(PROD_BRANCHES)),)
    debug_flag="-DDEBUG=true"
endif
ifeq($debug_flag,)
    debug_flag="-DDEBUG=false"
endif
于 2016-06-01T13:53:52.893 に答える