私は57の地方支部を持っています。そのうちの1つで特定のファイルに変更を加えたことは知っていますが、どれがどれかわかりません。特定のファイルへの変更が含まれているブランチを見つけるために実行できるコマンドはありますか?
回答:
FILENAMEへの変更を含むすべてのブランチを検索します((記録されていない)分岐点の前であっても)
FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u
手動で検査:
gitk --all --date-order -- $FILENAME
マスターにマージされていないFILENAMEへのすべての変更を検索します。
git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read x h; do if [ "`git log -n 1 --format=%H $h -- $FILENAME`" = "$h" ]; then echo $br; fi; done; done | sort -u
git log -Schange …
またはを使用できますかgit log --grep LOGMESSAGE …
(…は、前述のコマンドの残りの部分を表します)。
gitk --all -- filename
すると、そのファイルへのすべての変更がグラフィカルに表示されます。問題のコミットを特定できれば、それを使用git branch --contains
して、コミットが移行されたブランチを確認できます。問題のコミットが最初に作成されたブランチを確認したい場合は、google git-what-branchを実行しますが、早送りマージによってその情報が不明瞭になる可能性があることに注意してください。
git log --all --format='--contains %H' "$file" | xargs git branch
あなたに必要なのは
git log --all -- path/to/file/filename
ブランチをすぐに知りたい場合は、次を使用することもできます。
git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}
さらに、名前を変更した場合は--follow
、Gitlogコマンドに含めることをお勧めします。
--source
そこにを追加すると、あなたは金色になります。
これは適切な解決策がなくてもまだ問題のようです。コメントするのに十分なクレジットがないので、ここに私の小さな貢献があります。
Seth Robertsonの最初の解決策は私にとってはうまくいきましたが、ローカルブランチしか提供されませんでした。その中には、おそらく安定したブランチからのマージが原因で、多くの誤検知がありました。
Adam Dymitrukの2番目のソリューションは、私にはまったく機能しませんでした。手始めに、-format =%5とは何ですか?それはgitによって認識されず、それについて何も見つけることができず、他のフォーマットオプションで動作させることができませんでした。
しかし、彼の最初のソリューションを--sourceオプションと単純なgrepと組み合わせると、役に立ちました。
git log --all --source -- <filename> | grep -o "refs/.*" | sort -u
これにより、いくつかのリモートタグとブランチ、およびファイルに最新の変更を加えた1つのローカルブランチが得られます。これがどれほど完全かわからない。
@nealmcbの要求に従って更新し、最新の変更でブランチをソートします。
まず、grepを「refs / heads /.*」に変更できます。これにより、ローカルブランチのみが提供されます。ブランチが数個しかない場合は、次のように各ブランチの最新のコミットを調べることができます。
git log -1 <branch> -- <filename>
より多くのブランチがあり、これを本当に自動化したい場合は、xargs、gitログフォーマット、および別の並べ替えを使用して2つのコマンドをこのワンライナーに組み合わせることができます。
git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r
これにより、次のような出力が得られます。
2020-05-07T15:10:59+02:00 refs/heads/branch1
2020-05-05T16:11:52+02:00 refs/heads/branch3
2020-03-27T11:45:48+00:00 refs/heads/branch2
私はこの質問が古くからあることを知っていますが、私は自分自身の解決策を開発する前にそれに戻ってきました。マージベースの使用のおかげで、不要なブランチが除外され、よりエレガントに感じます。
#!/bin/bash
file=$1
base=${2:-master}
b=$(tput bold) # Pretty print
n=$(tput sgr0)
echo "Searching for branches with changes to $file related to the $base branch"
# We look through all the local branches using plumbing
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
# We're establishing a shared ancestor between base and branch, to only find forward changes.
merge_base=$(git merge-base $base $branch)
# Check if there are any changes in a given path.
changes=$(git diff $merge_base..$branch --stat -- $file)
if [[ ! -z $changes ]]; then
echo "Branch: ${b}$branch${n} | Merge Base: $merge_base"
# Show change statistics pretty formatted
git diff $merge_base..$branch --stat -- $file
fi
done
git-find-changes
(実行可能権限を使用して)としてPATHに配置すると、次のコマンドで呼び出すことができます。git find-changes /path
の出力例
git find-changes app/models/
Branch: update_callbacks | Merge base: db07d23b5d9600d88ba0864aca8fe79aad14e55b
app/models/api/callback_config.rb | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
Branch: repackaging | Merge base: 76578b9b7ee373fbe541a9e39cf93cf5ff150c73
app/models/order.rb | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
以下は、エレガントでないブルートフォース方式ですが、機能するはずです。現在使用しているブランチが切り替わるため、コミットされていない変更を最初に隠しておくようにしてください。
for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
git checkout $branch && git grep SOMETHING
done
git log -S
for-each-ref
それでもそのshort
フラグを尊重するかどうかはわかりませんが。そうは言っても、私の答えは無視してください。他の答えの方が良いです。