查找包含对给定文件所做更改的Git分支

查找包含对给定文件所做更改的Git分支,git,Git,我在当地有57家分行。我知道我对其中一个文件中的某个文件做了更改,但我不确定是哪一个。是否可以运行某种命令来查找哪些分支包含对某个文件的更改?查找所有包含文件名更改的分支(即使在(未记录的)分支点之前) 查找未合并到主文件的文件名的所有更改: git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read

我在当地有57家分行。我知道我对其中一个文件中的某个文件做了更改,但我不确定是哪一个。是否可以运行某种命令来查找哪些分支包含对某个文件的更改?

查找所有包含文件名更改的分支(即使在(未记录的)分支点之前)

查找未合并到主文件的文件名的所有更改:

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

下面是一个不雅观的暴力方法,但我希望它能起作用。首先确保您已经隐藏了任何未提交的更改,因为它将切换您当前所在的分支

for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
    git checkout $branch && git grep SOMETHING
done
你所需要的只是

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 {}

此外,如果您进行了任何重命名,您可能希望在Git log命令中包含
--follow

看起来这仍然是一个问题,没有适当的解决方案。我没有足够的学分发表评论,所以这里是我的一点贡献

Seth Robertson的第一个解决方案对我有点奏效,但只给了我本地分支,其中有许多误报,可能是因为来自稳定分支的合并

Adam Dymitruk的第二个解决方案对我根本不起作用。首先,什么是格式=%5?git无法识别它,我找不到任何关于它的信息,也无法让它与其他格式选项一起使用

但是他的第一个解决方案结合了--source选项和一个简单的grep被证明是有用的:

git log --all --source -- <filename> | grep -o "refs/.*" | sort -u

我知道这个问题由来已久,但在制定自己的解决方案之前,我一直在重复这个问题。我觉得它更优雅,这要感谢使用合并基过滤器来过滤掉不需要的分支

#!/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
(具有可执行权限)放在路径中,则可以使用
git find changes/PATH
调用它

示例输出
git查找应用程序/模型的更改

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(+)

除了文件名,我还需要替换此命令中的任何内容吗?它返回所有57个分支名称。@达斯汀:如果所有57个分支都包含该文件名,则所有57个分支都包含包含该文件名的更改。分支从该分支上可访问的最旧版本开始,即使该版本在创建分支之前存在(分支在某些意义上是追溯创建的)。我认为你需要更好地定义你的问题。你知道变化是什么吗?您可以使用
git log-Schange…
git log-grep LOGMESSAGE…
(其中…表示我提到的其余命令)。@Dustin:另一个选项是使用
gitk--all--filename
,它将以图形方式显示对该文件的所有更改。如果您可以识别有问题的提交,那么可以使用
git branch--contains
查看提交迁移到了哪些分支。如果您想查看问题中的提交最初是在哪个分支上创建的,那么google git将显示哪个分支,但请注意,快进合并可能会模糊该信息。@Seth:我记不起提交消息或确切的代码更改。我只是有个大概的想法。问题是它还没有与master合并,所以为了使用gitk,我仍然需要检查每个分支以找到我要查找的内容。如果我能说,“git,给我看看自其分支点以来对文件名进行了更改的分支”那就太好了。你可以更有效地编写第一行
git日志--all--format='--contains%H'$file”| xargs git branch
,因为如果你知道更改,你可以使用
git log-S
你假设的shell是什么?Bash?没有bashisms,应该可以在POSIX上使用。我不确定每个ref的
是否仍然尊重
short
标志。也就是说,忽略我的回答;其他答案更好。这将显示提交,但他问哪个分支。在那里添加一个
--source
,你就成功了。谢谢,但我认为这并没有显示每次提交的所有分支。但是这会有帮助。是的,但在这个特殊的例子中,他只是在为asp.net寻找一个.btw路径,它的格式应该是AppName/Controllers/XController.csGreat-谢谢。现在按最近的变化排序怎么样?非常有趣的脚本。向上投票。是显示更改还是查找更改?@VonC谢谢,正确的用法,应该随处可见
git log -1 <branch> -- <filename>
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
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(+)