12

__git_ps1しばらくの間、bashのPS1プロンプト(with)でこの関数を使用してきましたPS1='\w$(__git_ps1)'。ブランチの状態に応じて色を付けたいと思います。

現在のブランチが変更されているかどうかをチェックし、ステータスに応じて赤または白に色付けするbash関数を作成しました。問題はgit status、ステータスをチェックするために使用することです(これが私が知る唯一の方法です)__git_ps1。これは、プロンプトを使用しているときに迷惑な遅延を引き起こすのに十分な速度です(私は非常に弱いです)ネットブック)。

だから私は尋ねます:現在のgitフォルダーのステータスをチェックするより速い方法はありますか? __git_ps1手動で解析するよりもはるかに高速なgit branchので、他の隠されたgit関数があるのではないかと思います。

4

6 に答える 6

8

完全にあなたの答えではありませんが、bash-completionにはこれが組み込まれています。

bash ENV GIT_PS1_SHOWDIRTYSTATEを空でない値に設定すると、ステージングされていない(*)およびステージングされた(+)変更がブランチ名の横に表示されます。このリポジトリごとにbash.showDirtyState変数を構成できます。これは、GIT_PS1_SHOWDIRTYSTATEが有効になるとデフォルトでtrueになります。

GIT_PS1_SHOWSTASHSTATEを空でない値に設定することで、現在何かが隠されているかどうかを確認することもできます。何かが隠されている場合は、ブランチ名の横に「$」が表示されます。

追跡されていないファイルがあるかどうかを確認したい場合は、GIT_PS1_SHOWUNTRACKEDFILESを空でない値に設定できます。追跡されていないファイルがある場合は、ブランチ名の横に「%」が表示されます。

ただし、これを有効にすると速度が低下するかどうかはわかりません。あなたが着色をしたい場合:

ステージングされたファイル:

if git rev-parse --quiet --verify HEAD >/dev/null; then
 git diff-index --cached --quiet HEAD -- || color for staged changes
else
  color unstaged changes
fi

隠しファイル

git rev-parse --verify refs/stash >/dev/null 2>&1 && color for stashed files

追跡されていないファイル

if [ -n "$(git ls-files --others --exclude-standard)" ]; then
  Color untrack files
fi

上記のスニペットは、bash-completionスクリプトからのものです。

于 2012-06-20T15:37:56.833 に答える
6

注:Git 2.6以降(2015年第3四半期)はその__git_ps1ステータスを加速するはずです:

SZEDERGábor ( )によるcommit dd160d7commit 6bfab99(2015年7月19日)を参照してください。濱野純雄による合併---コミット461c1192015年8月3日szeder
gitster

bashプロンプト:追跡されていないディレクトリを使用した追跡されていないステータスインジケータの高速化

追跡されていないステータスインジケータが有効になっている場合は、__git_ps1()''を実行して追跡されていないファイルを探しますgit ls-files
追跡されていないディレクトリに多くのファイルが含まれている場合、追跡されていないディレクトリで見つかったすべてのファイルがリストされ、/dev/nullすぐにリダイレクトされるため、これはかなり遅くなる可能性があります。
これは、によって実行される実際のコマンド__git_ps1()です。

$ ls untracked-dir/ |wc -l
100000
$ time git ls-files --others --exclude-standard --error-unmatch \
  -- ':/*' >/dev/null 2>/dev/null

real    0m0.955s
user    0m0.936s
sys 0m0.016s

--directory --no-empty-directory' 'オプションを' 'に追加して渡すことにより、この遅延をなくしgit ls-files、すべてのコンテンツではなく、空でない追跡されていないディレクトリの名前のみを表示します

$ time git ls-files --others --exclude-standard --directory \
  --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null

real    0m0.010s
user    0m0.008s
sys 0m0.000s

これはea95c7bのスーツに従います(完了:ファイル名の完了のための追跡されていないディレクトリフィルタリングを改善します、2013-09-18、git 1.8.5)。


に影響を与えるコードの一部でリークフィックスが利用可能であるため、Git 2.29(2020年第4四半期)を必ず使用してくださいgit ls-files

Elijah Newren()によるcommit eceba53commit dad4f23(2020年8月18日)を参照してください。( Junio C Hamanoによってマージされました---コミットad00f44 、20208月24日)newren
gitster

dir:メモリリークを回避するために問題のあるAPIを修正

サインオフ-作成者:Elijah Newren

構造物のdir周りには多くの漏れや問題があるようでした。

最初に私はそれに気づき、リークされparent_hashmaprecursive_hashmapいました(ただし、Peffは私の前で修正に気づき、提出しました)。

次に、前回のコミットで、entries[]とignored[]を内部的に割り当てたにもかかわらず、clear_directory()内のフィールドのサブセットに対してのみ責任を負っていることに気づきました。 もちろん、その結果、多くの発信者がこれらのアレイとそのコンテンツをリークしたり、無計画に解放しようとしたりしました。dir_struct,dir.c

さらに掘り下げてみると、その上部にあるかなり明確なドキュメントにもかかわらず、ユーザーが不要になったときdir.hに電話をかけることになっていたにもかかわらず、まったく気にしない4人の発信者がいたことがわかりました。 しかし、そのうちの2つは、指令があったためにリークについて明確に考えていました。これは、データを解放する方法があまりにも不明確であったことを示唆しています。 APIの非自明性とその穴が、人々にAPIを回避させ、それが雪だるま式になって、、、および問題のさらなる問題に陥ったのではないかと思います。clear_directory()dir_struct,
UNLEAK(dir)
entries[]ignored[]parent_hashmap,recursive_hashmap

gitの他のデータ構造とより一致するように名前を変更し、すべてゼロへの提案されたmemsettingを処理するためのをclear_directory()導入します。 「」のような名前がより明確になり、の存在が、コードを見ている人に、aまたはaのいずれかを探して、を見つけるように導く必要があるというヒントを提供することを願っています。dir_clear()dir_init()dir_struct
"dir_clear()dir_init()dir_clear()dir_free()dir_clear()

それは影響します:

  • git add
  • git check-ignore
  • git clean
  • git grep
  • git ls-files
  • git stash
  • git merge
于 2015-08-16T21:08:30.137 に答える
5

git diff --quiet作業ディレクトリに変更がある場合は1を返しgit diff --quiet --cached、インデックスに対しても同じことを行います。

あなたはそれをするために使うことができます:

git diff --quiet
    || echo "There be changes!"
于 2012-06-20T18:36:22.147 に答える
2
! git diff-index --cached --quiet HEAD      # fastest staged-changes test
! git diff-files --quiet                    # fastest unstaged-changes test
! git diff-index --quiet          HEAD      # fastest any-changes test
stdbuf -oL git ls-files -o | grep -qs .     # fastest untracked-files test
git rev-parse -q --verify refs/stash >&-    # fastest any-stash test

無視されたステータスが追跡されていないファイルで重要な場合は--exclude-standard -oi、追跡されていない-無視されたファイルと追跡されていないおよび無視されていないファイルを使用します--exclude-standard -o

HEADモニカ(ブランチ名またはsha)を取得するために私が知っている最速の方法は

{ git symbolic-ref -q --short HEAD || git rev-parse -q --short --verify HEAD; } 2>&-

リポジトリにいない場合はリターンコードが残るので、たとえば

if HEAD=`{ git symbolic-ref -q --short HEAD || git rev-parse -q --verify HEAD;  } 2>&-`
then
        : in a git repo, $HEAD is the branch name or sha
fi

untracked-filesテストは、shopt -s lastpipeforでの実行に依存することに注意してbashください。 zshデフォルトではそのようにksh動作します。

于 2019-05-04T17:45:07.970 に答える
0

kshを使用していますが、同じ問題が発生しています。さらに、私のGitリポジトリはNFSマウント上にあるため、応答時間がさらに遅くなります。

速度に関する質問に直接答えるには、次を使用してみてください。

git ls-files -m

最初に別のリポジトリに入った後は、「gitstatus-s」よりも大幅に高速であるように見えます。リポジトリ内に入ると、OSとNFSのキャッシュがこのコマンドを大幅に高速化するように見えます。このコマンドは、git作業ディレクトリツリーの下部リーフの奥深くにある場合にも非常に高速であるように見えます。

于 2014-05-23T15:16:55.437 に答える
0

すべてのソリューションは、git最終的にgit実行速度に上限があります。gitいくつかのfs-monitoringフックをgitにフィードすることで、それよりも速く実行することができます。

または、次のように、より少ない作業を行うことができます--directory --no-empty-directory

于 2020-05-14T03:48:52.597 に答える