Makefileで、コミットされていない変更(作業ツリーまたはインデックスのいずれか)がある場合、特定のアクションを実行したいと思います。それを行うための最もクリーンで最も効率的な方法は何ですか?ある場合はゼロの戻り値で終了し、他の場合はゼロ以外の値で終了するコマンドは、私の目的に適しています。
git status
出力を実行してにパイプすることができますgrep
が、もっと良い方法があるはずだと感じています。
Makefileで、コミットされていない変更(作業ツリーまたはインデックスのいずれか)がある場合、特定のアクションを実行したいと思います。それを行うための最もクリーンで最も効率的な方法は何ですか?ある場合はゼロの戻り値で終了し、他の場合はゼロ以外の値で終了するコマンドは、私の目的に適しています。
git status
出力を実行してにパイプすることができますgrep
が、もっと良い方法があるはずだと感じています。
回答:
更新:OP Daniel Stutzbach は、この簡単なコマンドgit diff-index
が彼のために機能したことをコメントで指摘しています:
git update-index --refresh
git diff-index --quiet HEAD --
(nornagonはコメントで、触れられたファイルがあり、その内容がインデックスと同じである場合、git update-index --refresh
前に実行する必要があることを述べています。git diff-index
そうしないdiff-index
と、ツリーがダーティであると誤って報告されます)
その後、bashスクリプトで使用している場合は、「コマンドが成功したかどうかを確認する方法」を確認できます。
git diff-index --quiet HEAD -- || echo "untracked"; // do something about it
注:Anthony Sottileによるコメント
git diff-index HEAD ...
コミットされていないブランチ(新しく初期化されたリポジトリなど)では失敗します。
私が見つけた1つの回避策はgit diff-index $(git write-tree) ...
そして、コメントでharidsv
指摘するように、新しいファイルでは差分として検出されません。
より安全なアプローチは、最初にファイル仕様で実行し、次に実行前にインデックスに何かが追加されたかどうかを確認することです。git diff-files
git add
git diff-index
git commit
git add ${file_args} && \ git diff-index --cached --quiet HEAD || git commit -m '${commit_msg}'
そして6502はコメントで報告します:
私がぶつかった1つの問題は、
git diff-index
実際にはファイルのタイムスタンプ以外に違いがない場合に、違いがあることがわかるということです。一度
実行git diff
すると問題が解決します(驚くほど十分に、git diff
実際にはサンドボックスの内容が変更されます。つまり、ここで意味します.git/index
)。
これらのタイムスタンプの問題は、gitがdockerで実行されている場合にも発生する可能性があります。
元の答え:
「プログラム的に」とは、磁器のコマンドに決して依存しないことを意味します。
常に配管コマンドに依存します。
代替手段(など)については、「Gitを使用したダーティインデックスまたは追跡されていないファイルの確認」も参照してください。git status --porcelain
私たちが話すにつれて書かれた新しい「require_clean_work_tree
機能」からインスピレーションを得ることができます ;)(2010年10月初旬)
require_clean_work_tree () {
# Update the index
git update-index -q --ignore-submodules --refresh
err=0
# Disallow unstaged changes in the working tree
if ! git diff-files --quiet --ignore-submodules --
then
echo >&2 "cannot $1: you have unstaged changes."
git diff-files --name-status -r --ignore-submodules -- >&2
err=1
fi
# Disallow uncommitted changes in the index
if ! git diff-index --cached --quiet HEAD --ignore-submodules --
then
echo >&2 "cannot $1: your index contains uncommitted changes."
git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2
err=1
fi
if [ $err = 1 ]
then
echo >&2 "Please commit or stash them."
exit 1
fi
}
git diff-index --quiet HEAD
。
HEAD
作業ディレクトリにファイルが呼び出されていると、失敗する可能性があります。よく使うgit diff-index --quiet HEAD --
。
git status --help
は次のよう に記載されています 。--porcelain スクリプトの解析しやすい形式で出力を提供します。これは短い出力に似ていますが、ユーザー設定に関係なく、Gitバージョン全体で安定したままです。詳細については、以下を参照してください。
他の解決策は非常に徹底していますが、本当に迅速で汚いものが必要な場合は、次のような方法を試してください。
[[ -z $(git status -s) ]]
ステータスの概要に出力があるかどうかを確認するだけです。
[[ ... ]]
ますが、構文が実際に何をしているのかわかりますか?私はそのようなものを見たことがありません。
--porcelain
示すように、パラメータここで
git status -s -uall
して、追跡されていないファイルを含めることができます。
git diff --exit-code
変更がある場合はゼロ以外を返します。git diff --quiet
出力なしで同じです。作業ツリーとインデックスを確認したいので、
git diff --quiet && git diff --cached --quiet
または
git diff --quiet HEAD
ステージングされているかどうかにかかわらず、コミットされていない変更があるかどうかがわかります。
git diff --quite HEAD
は、作業ツリーがクリーンであるかどうかを通知するだけで、インデックスがクリーンであるかどうかは通知しません。たとえば、file
HEAD〜とHEADの間で変更された場合、の後git reset HEAD~ -- file
、インデックスに段階的な変更が存在していても(wt == HEAD、ただしインデックス!= HEAD)、0を終了します。
git diff --quiet && git diff --cached --quiet
。
@Neptharの答えを拡張する:
if [[ -z $(git status -s) ]]
then
echo "tree is clean"
else
echo "tree is dirty, please commit changes before running this"
exit
fi
$(git status -s "$file")
、else
節の中で使用しますgit add "$file"; git commit -m "your autocommit process" "$file"
git status -s
git status --porcelain ; git clean -nd
git status
他の答えで指摘されているように、そのようなコマンドで十分です:
git diff-index --quiet HEAD --
最後の2つのダッシュを省略すると、という名前のファイルがある場合、コマンドは失敗しますHEAD
。
例:
#!/bin/bash
set -e
echo -n "Checking if there are uncommited changes... "
trap 'echo -e "\033[0;31mFAILED\033[0m"' ERR
git diff-index --quiet HEAD --
trap - ERR
echo -e "\033[0;32mAll set!\033[0m"
# continue as planned...
注意:このコマンドは、追跡されていないファイルを無視します。
git add
そしてgit clean
救助に
いくつかの便利なgitエイリアスを作成して、ステージングされていないファイルとステージングされたファイルをリストします。
git config --global alias.unstaged 'diff --name-only'
git config --global alias.staged 'diff --name-only --cached'
その後、次のようなことを簡単に行うことができます。
[[ -n "$(git unstaged)" ]] && echo unstaged files || echo NO unstaged files
[[ -n "$(git staged)" ]] && echo staged files || echo NO staged files
PATH
呼び出し先のどこかにスクリプトを作成して、読みやすくすることができますgit-has
。
#!/bin/bash
[[ $(git "$@" | wc -c) -ne 0 ]]
上記の例は、次のように簡略化できます。
git has unstaged && echo unstaged files || echo NO unstaged files
git has staged && echo staged files || echo NO staged files
完全を期すために、追跡されず無視されたファイルの同様のエイリアスを次に示します。
git config --global alias.untracked 'ls-files --exclude-standard --others'
git config --global alias.ignored 'ls-files --exclude-standard --others --ignored'
これが最良で最もクリーンな方法です。
function git_dirty {
text=$(git status)
changed_text="Changes to be committed"
untracked_files="Untracked files"
dirty=false
if [[ ${text} = *"$changed_text"* ]];then
dirty=true
fi
if [[ ${text} = *"$untracked_files"* ]];then
dirty=true
fi
echo $dirty
}
git status
「磁器」コマンドです。磁器のコマンドはgitのバージョン間で変わる可能性があるため、スクリプトでは使用しないでください。代わりに、「配管」コマンドを使用してください。
git status --porcelain
(これはこの目的のために意味します-スクリプトで解析できる安定したフォーマット)、おそらく-z(改行の代わりにnullで区切られていますか?) 。@ codyc4321詳細については、stackoverflow.com / questions / 6976473 /… を参照