한 커밋이 다른 커밋의 자손인지 어떻게 알 수 있습니까?


답변:


51

프로그래밍 방식으로 (예 : 스크립트에서) 확인 git merge-base A B하려면 git rev-parse --verify A(B에서 ​​A에 도달 할 수 있는지 ) 또는 (A에서 B에 도달 할 수 있는지) 확인할 수 있습니다 git rev-parse --verify B. git rev-parse커밋 이름에서 커밋 SHA-1 / 커밋 ID로 변환하는 데 필요합니다.

VonCgit rev-list 에서와 같은 답변을 사용하는 것도 가능합니다.

편집 : 현대 Git에는이 쿼리에 대한 형식이 명시 적으로 지원됩니다 git merge-base --is-ancestor.


당신이 요구하는 커밋 중 하나에 대한 경우 지점 팁 , 다음 git branch --contains <commit>또는 git branch --merged <commit>더 나은 비 프로그램의 솔루션이 될 수 있습니다.


1
아마도 가장 빠른 방법은하는 것 git checkout -b quickcheck <more-recent-commit-ID>다음 git branch --contains <older-commit-ID>(다음 git branch -D quickcheck임시 지점을 제거하기 위해).
clee

2
두 가지 가능한 접근 방식, 둘 다 @MattR의 대답보다 훨씬 나쁩니다.
jwg

6
@ jwg : MattR 답변이 더 좋지만이 답변은 아마도 git 1.8.0보다 git merge-base --is-ancestor2 년 더 빠릅니다 .
Jakub Narębski

@ JakubNarębski Fair, 충분히 죄송합니다.
jwg

2
큰 저장소 (200 만 커밋)에서, 나는 속도 비교 git branch --contains <commit>git merge-base --is-ancestor ...0.14s 대 3m40s :
hagello

259

Git 1.8.0부터는 다음과 같은 옵션으로 지원됩니다 merge-base.

git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>

매뉴얼 페이지에서 :

-조상

첫 번째가 두 번째의 조상인지 확인하고 true이면 상태 0으로, 그렇지 않으면 상태 1로 종료하십시오. 오류는 1이 아닌 0이 아닌 상태로 표시됩니다.

예를 들면 다음과 같습니다.

git merge-base --is-ancestor origin/master master; echo $?

4
좋은! 여기에 인간 reabable 출력 뭔가이 답변을 감싸는 쉘 스크립트는 다음과 같습니다 gist.github.com/simonwhitaker/6354592은
사이먼 휘태커

1
다시 말해 : git merge-base THING --is-ancestor OF_THING && echo yes || echo no예 :git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
user1735594

2
@smarber git merge-base --is-ancestor -- commit commit는 현재 git2.1.4 (Debian / Devuan 7.10 jessie) 및 1.9.1 (Ubuntu 14.04 trusty) 로 해시 작업을 하고 있습니다. 그렇게하면 데비안 wheezy에서도 작동합니다 sudo apt-get install git/wheezy-backports.
티노

15

이러한 종류의 작업은 SO 질문에 자세히 설명 된 수정 범위의 개념에 의존합니다 . " 'git log origin / master'와 'git log origin / master ..'의 차이 "

git rev-list 도달 할 수있는 다른 커밋까지 커밋에서 되돌아 갈 수 있어야합니다.

그래서 시도 할 것입니다 :

git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20

(경계 커밋은 접두사가 붙습니다 -)

표시된 마지막 커밋이 git rev-list명령 의 첫 번째 커밋과 동일 하면 두 번째 커밋에서 도달 가능한 커밋입니다.

첫 번째 커밋이 두 번째 커밋에 도달 할 수 git rev-list없으면 아무것도 반환하지 않아야합니다.

git rev-list --boundary A..B

에서 도달 할 수있는 A경우에 완료됩니다 . 다음과 같습니다.AB

git rev-list --boundary B --not A

함께 포지티브 기준제외 참조 . 에서 도달 할 수있는 개정판을 발견 할 때까지 그래프 에서 시작 하여 그래프를 다시 살펴 봅니다. 에서 직접 연결할 수 있으면 옵션 과 관련하여 표시 됩니다.BA
BA
AB--boundaryA


이것은 git이 정확히 이것을 수행하는 "porcelain"명령을 아직 게시하지 않은 것에 대해 놀랍게도 일반적인 사용 사례처럼 들립니다.
로렌스 I. Siden

1
@lsiden : 맞습니다. 참고 사항 : 프로그래밍 방식으로 무언가를 검사 하기 위해서는 도자기 명령 ( stackoverflow.com/questions/6976473/… 과 같이)을 사용하지 말고 배관 명령 ( stackoverflow.com/questions에 설명되어 있음)을 잊지 마십시오. / 3878624 /… )
VonC

아, 다시 돌아가서 쉘 스크립팅 작업을해야하는 것 같습니다!
로렌스 I. Siden

1
질문 : -85e54e2...스 니펫의 왜 마이너스가 있습니까? 또한 가능한 오타 : "...는 첫 번째 커밋과 같습니다 ..."
sdaau

1
@sdaau -는 경계 커밋 임을 의미합니다. 나는 문서 링크를 새로 고치고 5 년 된이 답변의 오타를 수정하고 명확하게하기 위해 답변을 편집했습니다.
VonC

11

또 다른 방법은 git log및 을 사용하는 것 grep입니다.

git log --pretty=format:%H abc123 | grep def456

commit def456이 commit abc123의 조상이거나 그렇지 않으면 출력이 없으면 한 줄의 출력을 생성합니다.

일반적으로 --pretty인수 를 생략하여 벗어날 수는 있지만 로그 주석 등이 아닌 실제 커밋 해시를 통해서만 검색하도록하려면 필요합니다.


나는이 솔루션은 느린 것으로 예상하지만, 그것도 20K + 커밋과 프로젝트에 대한 매우 빠른 실제로
레나토 Zannon

2
대신 --pretty내가 --oneline를 사용 : git log --oneline ce2ee3d | grep ec219cc좋은 작품
씨족에게

3

https://stackoverflow.com/a/13526591/895245에서 더 인간 친화적으로 만들기 위해 언급했습니다.

git-is-ancestor() (
  if git merge-base --is-ancestor "$1" "$2"; then
      echo 'ancestor'
  elif git merge-base --is-ancestor "$2" "$1"; then
      echo 'descendant'
  else
      echo 'unrelated'
  fi
)
alias giia='git-is-ancestor'

두 매개 변수가 모두 동일한 커밋을 가리키는 경우 '관련되지 않음'을 반환합니다.
mik

1

git show-branch branch-sha1 커밋 -sha1

어디:

  • branch-sha1 : 확인하려는 지점의 sha1
  • commit-sha1 : 확인할 커밋의 sha1

0

당신이 사용하는 경우 git merge-base --is-ancestor , 힘내 2.28을 사용해야합니다 (Q3 2020)

Git 2.28 (Q3 2020)에서는 struct commit항상 존재하지 않아도 되는 " " 의 일부 필드가 슬래브를 커밋하도록 이동되었습니다.

참조 c752ad0 커밋 , c49c82a 커밋 , 4,844,812 커밋 , 6da43d9 커밋 에 의해 (2020 6월 17일) (Abhishek 쿠마 abhishekkumar2718) .
(의해 병합 Junio C 하마노 - gitster-커밋 d80bea4 06 7 월를 2020)

commit-graph: 설명하다 commit_graph_data_slab

서명자 : Abhishek Kumar

구조체 커밋은 많은 상황에서 사용됩니다. 그러나, 부재 generation와는 graph_pos단지 저지 그래프 관련 작업에 사용하고, 그렇지 않으면 메모리를 낭비.

이 낭비는 현재 32 비트 대신 64 비트 세대 번호를 사용하는 세대 번호 v2로 전환함에 따라 더욱 두드러졌습니다.

그들은 종종 함께 접근하기 때문에 구조체를 소개 commit_graph_data하고 commit_graph_data슬래브 로 옮깁니다 .

전체 테스트 스위트는 master(26m48s, master27m34s, 2.87 % 더 빠름) git merge-base --is-ancestor속도로 실행 되지만 Szeder Gábor가 발견 한 것과 같은 특정 명령 은 40 % 느려졌습니다 .
커밋 슬래브 액세스를 최소화 한 후에도 속도가 느려지지만 20 %에 가깝습니다.

데릭 스토리 (Derrick Stolee) 는 커밋 슬래브 액세스 속도 가 느리지 않고 기본 알고리즘에 기인한다고 느꼈으 며 이후 시리즈에서 후속 조치를 취할 것입니다.


-1

저장소의 모든 태그에 대해이 작업을 수행 해야하는 경우 itub의 답변을 작성하십시오.

for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.