답변:
귀하의 예는 브랜치 feature
를 여전히 사용할 수 있음을 보여줍니다 .
이 경우 h
마지막 결과는 다음과 같습니다.
git log master ^feature --ancestry-path
feature
더 이상 지점을 사용할 수없는 경우 c
및 사이의 내역 행에 병합 커밋을 표시 할 수 있습니다 master
.
git log <SHA-1_for_c>..master --ancestry-path --merges
그러나 이것은 또한 이후에 일어난 모든 병합 표시됩니다 h
, 사이 e
와 g
에가 feature
.
다음 명령의 결과 비교
git rev-list <SHA-1_for_c>..master --ancestry-path
git rev-list <SHA-1_for_c>..master --first-parent
SHA-1을 h
마지막 행으로 공통으로 제공합니다.
사용 가능한 comm -1 -2
경우이 결과에 사용할 수 있습니다 . msysgit을 사용중인 경우 다음 펄 코드를 사용하여 비교할 수 있습니다.
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
( http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/의 펄 코드 . "comp.unix.shell 뉴스 그룹의 누군가"에서 가져온 것입니다).
하나의 라이너로 만들려면 프로세스 대체를 참조하십시오 .
master
에 병합 된 feature
후 즉시 feature
로 병합 master
빨리 감기 (의 설명으로 feature
대체합니다 master
). 그로 인해 --first-parent
잘못된 부모가 반환됩니까?
comm -1 -2
했지만 작동하지 않았습니다. comm
정렬 된 줄에서만 작동합니다. (Perl one-liner는 읽을 수는 없지만 작동합니다.)
git find-merge h master
(h는 반환하지만 아무것도 반환하지 않아야 함), git find-merge d master
(f는 반환하지만 d git find-merge c feature
는 반환해야 함)
이것을 다음에 추가하십시오 ~/.gitconfig
.
[alias]
find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
그런 다음 다음과 같이 별칭을 사용할 수 있습니다.
# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
병합 커밋 메시지 및 기타 세부 정보를 보려면 git show-merge
동일한 인수와 함께 사용하십시오 .
( Gauthier의 답변을 기반으로합니다 . 로 문제를 해결 한 Rosen Matev 와 javabrett 에게 감사드립니다 sort
.)
sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2
마지막 행을 올바르게 찾지 못하는 것에 주의하십시오 . 다음은 실패한 예입니다.
16db9fef5c581ab0c56137d04ef08ef1bf82b0b7
붙여 넣기에서 실행할 때 여기에서 발견 됩니다. 어떤 OS를 사용하고 있습니까?
29c40c3a3b33196d4e79793bd8e503a03753bad1
git-get-merge 는 찾고있는 병합 커밋을 찾아서 보여줍니다 :
pip install git-get-merge
git get-merge <SHA-1>
명령은 다른 분기 (아마도 마스터) 로의 병합 이 발견 될 때까지 지정된 커밋의 자식을 따릅니다 .
즉, Gauthier의 게시물을 요약하면 다음과 같습니다.
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1
편집 : 이것은 프로세스 대체 " <()
"를 사용하기 때문에 POSIX와 호환되지 않으며 쉘에서 작동하지 않을 수 있습니다. 그것은 작동 bash
또는 zsh
불구하고.
나는 이것을해야했고 어떻게 든 발견했다 git-when-merged
(실제로이 SO 질문을 참조하지만 Michael Haggerty는 그의 멋진 Python 스크립트에 대한 참조를 여기에 추가하지 않았다). 그래서 지금 가지고 있습니다.
Gauthier의 훌륭한 답변을 바탕으로 comm
목록을 비교하는 데 사용할 필요는 없습니다 . 우리 --ancestry-path
는 또한에 있는 마지막 결과를 찾고 있기 때문에 --first-parent
전자의 출력에서 후자를 grep 할 수 있습니다.
git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1
또는 간단하고 재사용 가능한 무언가를 위해 다음과 같은 기능이 있습니다 .bashrc
.
function git-find-merge() {
git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}
comm
입력이 정렬되지 않은 경우 작동하지 않았습니다.
Ruby 사용자에게는 git-whence가 있습니다. 아주 쉽게.
$ gem install git-whence
$ git whence 1234567
234557 Merge pull request #203 from branch/pathway
나는 path에 배치하는 bash 스크립트를 사용합니다 ~/bin/git-find-merge
. 그것은 코너 케이스를 처리하기 위해 약간의 조정 으로 Gauthier의 답변 과 evilstreak의 답변 을 기반으로 합니다. comm
입력이 정렬되지 않은 경우 발생합니다. grep -f
완벽하게 작동합니다.
코너 케이스 :
~/bin/git-find-merge
스크립트:
#!/bin/bash
commit=$1
if [ -z $commit ]; then
echo 1>&2 "fatal: commit is required"
exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}
# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
git log -1 $commit
exit
fi
# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
cut -d' ' -f1 | \
grep $commit | wc -l) -eq 1 ]]; then
if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
# if commit is a merge commit
git log -1 $commit
else
# if commit is a NON-merge commit
echo 1>&2 ""
echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
echo 1>&2 ""
git log -1 $branch
fi
exit
fi
# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
<(git rev-list --first-parent $commit..$branch) \
<(git rev-list --ancestry-path $commit..$branch) \
| tail -1)
if [ ! -z $merge ]; then
git log -1 $merge
exit
fi
# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1
내가 이것을 할 수있게하십시오 :
(master)
$ git find-merge <commit> # to find when commit merged to current branch
$ git find-merge <branch> # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch
이 스크립트는 내 github 에서도 사용할 수 있습니다 .
@ robinst 아이디어의 루비 버전은 두 배 더 빠르게 작동합니다 (이전 커밋을 검색 할 때 중요합니다).
find-commit.rb
commit = ARGV[0]
master = ARGV[1] || 'origin/master'
unless commit
puts "Usage: find-commit.rb commit [master-branch]"
puts "Will show commit that merged <commit> into <master-branch>"
exit 1
end
parents = `git rev-list #{commit}..#{master} --reverse --first-parent --merges`.split("\n")
ancestry = `git rev-list #{commit}..#{master} --reverse --ancestry-path --merges`.split("\n")
merge = (parents & ancestry)[0]
if merge
system "git show #{merge}"
else
puts "#{master} doesn't include #{commit}"
exit 2
end
다음과 같이 사용할 수 있습니다.
ruby find-commit.rb SHA master
이런 식으로 시도해 볼 수 있습니다. 아이디어는 모든 병합 커밋을 반복하고 커밋 "c"에 도달 할 수 있는지 확인하는 것입니다.
$ git log --merges --format='%h' master | while read mergecommit; do
if git log --format='%h' $mergecommit|grep -q $c; then
echo $mergecommit;
break
fi
done
git rev-list <SHA-1_for_c>..master --ancestry-path --merges
나는 이것을 여러 번 (이 질문에 대답 한 모든 사람에게 감사드립니다!)해야했고, 작은 git 유틸리티 모음에 추가 할 수있는 스크립트 (Gauthier의 방법을 사용하여)를 작성했습니다. https://github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point에서 찾을 수 있습니다 .