주어진 파일에 대한 변경 사항을 포함하는 Git 브랜치 찾기


88

저는 57 개의 지역 지점이 있습니다. 그중 하나에서 특정 파일을 변경 한 것을 알고 있지만 어떤 파일인지 잘 모르겠습니다. 특정 파일에 대한 변경 사항이 포함 된 분기를 찾기 위해 실행할 수있는 일종의 명령이 있습니까?

답변:


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

@Dustin : 57 개의 모든 분기에 해당 파일 이름이 포함되어 있으면 57 개의 모든 분기에 해당 파일 이름을 포함하는 변경 사항이 포함됩니다. 브랜치는 브랜치를 생성하기 전에 해당 리비전이 존재 했더라도 해당 브랜치에서 도달 할 수있는 가장 오래된 리비전에서 시작합니다 (분기는 어떤 의미에서 소급하여 생성됨). 문제를 더 잘 정의해야한다고 생각합니다. 변화가 무엇인지 아십니까? git log -Schange …또는 git log --grep LOGMESSAGE …(내가 언급 한 나머지 명령을 나타내는…과 함께) 를 사용할 수 있습니까 ?
Seth Robertson

2
@Dustin : 또 다른 옵션은 gitk --all -- filename해당 파일의 모든 변경 사항을 그래픽으로 표시 하는 사용 입니다. 문제의 커밋을 식별 할 수있는 경우을 사용 git branch --contains하여 커밋이 마이그레이션 된 분기를 확인할 수 있습니다 . 문제의 커밋이 원래 생성 된 브랜치를 확인하려면 google git-what-branch를 사용하지만 빨리 감기 병합이 해당 정보를 가릴 수 있습니다.
Seth Robertson

@Seth : 커밋 메시지 나 정확한 코드 변경을 기억하지 못했습니다. 일반적인 생각이 있습니다. 문제는 아직 master와 병합되지 않았기 때문에 gitk를 사용하려면 원하는 항목을 찾기 위해 각 분기를 확인해야합니다. 내가 말할 수 있다면 "자식, 나에게 그 분기점 이후 파일 이름 변경 한 가지를 보여"좋은 일 것
더스틴

1
당신은보다 효율적으로 첫 줄을 쓸 수git log --all --format='--contains %H' "$file" | xargs git branch
코지로

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

또한 이름 --follow이 변경된 경우 Git 로그 명령 에 포함 할 수 있습니다 .


15
그것은 커밋을 보여줄 것이지만 그는 어떤 브랜치를 물었습니다. --source거기에 추가하면 황금색입니다.
Karl Bielefeldt 2011

고맙지 만 각 커밋에 대한 모든 분기를 보여주지는 않는다고 생각합니다. 그러나 그것은 도움이 될 것입니다.
Adam Dymitruk 2011-06-06

1
사실이지만이 특별한 경우에는 하나만 찾고있었습니다.
Karl Bielefeldt 2011

BTW asp.net에 대한 경로는 프로그램 응용 / 컨트롤러 / XController.cs 같은 형식이어야합니다
알리 카라 카

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 log 형식화 및 다른 정렬을 사용하여 두 명령을 결합 할 수 있습니다.

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

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

매우 흥미로운 스크립트입니다. 찬성. 변경 사항을 표시합니까 아니면 변경 사항을 찾습니까?
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

당신은 어떤 껍질을 가지고 있습니까? 세게 때리다?
Peter Mortensen

POSIX에서 작동해야하는 바 시즘이 없습니다. for-each-ref그래도 여전히 그 short깃발을 존중 하는지 모르겠습니다 . 즉, 내 대답을 무시하십시오. 다른 답변이 더 좋습니다.
whiteinge
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.