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


88

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

Answers:


87

查找所有包含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

除了FILENAME,我是否需要替换此命令中的任何内容?它返回所有57个分支名称。
达斯汀

@Dustin:如果所有57个分支都包含该文件名,则所有57个分支都包含一个包含该文件名的更改。分支从该分支上可访问的最早的修订版本开始,即使该修订版本在创建分支之前就已经存在(从某种意义上说,该分支是追溯创建的)。我认为您需要更好地定义问题。你知道改变是什么吗?您能否使用git log -Schange …git log --grep LOGMESSAGE …(带有…代表我提到的其余命令)。
塞斯·罗伯逊

2
@Dustin:另一个选择是使用gitk --all -- filename它将以图形方式显示该文件的所有更改。如果您可以确定所涉及的提交,则可以git branch --contains用来查看提交已迁移到的分支。如果您想查看最初在哪个分支上创建提交的问题,请google git-what-branch,但请注意,快速合并会掩盖该信息。
塞斯·罗伯逊

@Seth:我不记得提交消息或确切的代码更改。我只是有一个大致的想法。问题在于它尚未与master合并,因此,要使用gitk,我仍然必须签出每个分支以查找所需的内容。如果我能说“ git,请向我展示自文件分支点以来对FILENAME进行更改的分支”,那就很好了
Dustin

1
您可以更有效地编写第一行git log --all --format='--contains %H' "$file" | xargs git branch
kojiro 2014年

52

所有你需要的是

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

此外,如果您有任何重命名,则可能要包括--followGit log命令。


15
那将显示提交,但是他问哪个分支。在上面添加一个--source,您就很赞了。
Karl Bielefeldt

谢谢,但是我认为这不会显示每次提交的所有分支。但这会有所帮助。
亚当·迪米特鲁克

1
没错,但在这种情况下,他只想找一个。
Karl Bielefeldt

asp.net路径的btw应该采用类似AppName / Controllers / XController.cs的格式
Ali Karaca

8

如果没有适当的解决方案,这似乎仍然是一个问题。我没有足够的积分来发表评论,所以这是我的一点贡献。

塞思·罗伯森(Seth Robertson)的第一种解决方案对我来说有点用,但只给了我本地分支机构,其中有许多误报,可能是因为稳定分支机构合并了。

亚当·迪米特鲁克(Adam Dymitruk)的第二个解决方案根本不适合我。对于初学者来说,--format =%5是什么?git无法识别它,我找不到任何信息,也无法与其他格式选项一起使用。

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

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

这给了我许多远程标记和分支,以及一个本地分支,在这里我对该文件进行了最新更改。不知道这有多完整。

根据@nealmcb的请求进行更新,按最新更改对分支进行排序:

首先,您可以将grep更改为“ refs / heads /.*”,这将只为您提供本地分支机构。如果只有几个分支,则可以像这样检查每个分支的最新提交:

git log -1 <branch> -- <filename>

如果还有更多分支,并且您确实要自动化,可以使用xargs,git日志格式和这两种格式将这两种命令组合在一起:

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

太好了谢谢。现在如何根据最新更改进行排序?
nealmcb

1

我知道这个问题很古老,但是在开发自己的解决方案之前,我一直回头再问。我觉得它更优雅,这要归功于使用合并基础过滤掉不需要的分支。

#!/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(+)

非常有趣的脚本。已投票。它是显示更改还是查找更改?
VonC

@VonC谢谢,改正用法,应该随处可见
Marcin Raczkowski

0

以下是一种蛮力的蛮力方法,但我希望它可以工作。确保您先隐藏了所有未提交的更改,因为它将切换您当前所在的分支。

for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
    git checkout $branch && git grep SOMETHING
done

1
因为如果您知道更改,可以使用git log -S
Seth Robertson

你假设什么壳?重击?
彼得·莫滕森

没有bashisms,应该在POSIX上起作用。我不确定那for-each-ref还是尊重那个short标志。也就是说,请忽略我的回答;其他答案更好。
whiteinge
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.