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

Dus*_*tin 74 git

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

Set*_*son 77

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

FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u
Run Code Online (Sandbox Code Playgroud)

手动检查:

gitk --all --date-order -- $FILENAME
Run Code Online (Sandbox Code Playgroud)

查找未合并到master的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
Run Code Online (Sandbox Code Playgroud)

  • @Dustin:另一种选择是使用`gitk --all -- filename`,它将以图形方式显示对该文件的所有更改。如果您可以识别有问题的提交,那么您可以使用 `git branch --contains` 来查看提交已迁移到哪些分支。如果您想查看所讨论的提交*最初* 创建在哪个分支上,请使用 google git-what-branch,但请注意,快进合并可能会掩盖该信息。 (2认同)

Ada*_*ruk 45

所有你需要的是

git log --all -- path/to/file/filename
Run Code Online (Sandbox Code Playgroud)

如果您想立即了解分支,您还可以使用:

git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}
Run Code Online (Sandbox Code Playgroud)

此外,如果您有任何重命名,您可能希望包含--followGit log命令.

  • 这将显示提交,但他问哪个分支.在那里添加一个`--source`,你就是金色的. (12认同)

Sim*_*ton 9

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

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

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

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

git log --all --source -- <filename> | grep -o "refs/.*" | sort -u
Run Code Online (Sandbox Code Playgroud)

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

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

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

git log -1 <branch> -- <filename>
Run Code Online (Sandbox Code Playgroud)

如果有更多分支并且你真的想自动化这个,你可以使用 xargs、git log 格式和另一种排序将这两个命令组合到这个单行中:

git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r
Run Code Online (Sandbox Code Playgroud)

这将导致如下输出:

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*ski 6

我知道这个问题很古老,但在开发自己的解决方案之前,我不断地回顾这个问题。我觉得它更优雅,并且由于使用合并基础过滤掉了不需要的分支。

#!/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
Run Code Online (Sandbox Code Playgroud)

如果你把它放在 PATH 中git-find-changes(具有可执行权限) - 然后你可以用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(+)
Run Code Online (Sandbox Code Playgroud)