주어진 파일에 대한 변경 사항을 포함하는 Git 브랜치 찾기 것을 알고 있지만 어떤

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



답변

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 --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 로그 명령 에 포함 할 수 있습니다 .


답변

적절한 해결책이 없으면 여전히 문제인 것 같습니다. 댓글을 올릴 크레딧이 충분하지 않으므로 여기에 약간의 공헌이 있습니다.

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


답변

나는이 질문이 오래되었다는 것을 알고 있지만, 내 자신의 해결책을 개발하기 전에 계속해서 다시 질문했습니다. 나는 그것이 더 우아하고 원치 않는 분기를 필터링하는 병합 기본 필터를 사용하여 더 우아하다고 느낍니다.

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


답변

다음은 무차별 대입 방법이지만 제대로 작동 할 것으로 예상합니다. 커밋되지 않은 변경 사항을 먼저 숨겼는지 확인하십시오. 그러면 현재 어떤 분기에 있는지 전환됩니다.

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


답변