Git-특정 브랜치의 첫 번째 커밋을 찾는 방법


93

다음 예제 트리에서 :

A-B-C-D-E (master branch)
    \
     F-G-H (xxx branch)

xxx 지점의 첫 번째 커밋 인 F를 찾고 있습니다. 다음과 같이 가능하다고 생각합니다.

git log xxx --not master

마지막으로 나열된 커밋은 F 여야합니다. 올바른 솔루션입니까 아니면 단점이 있습니까?

나는 stackoverflow에 비슷한 질문이 있다는 것을 알고 있지만 아무도 그러한 솔루션을 제안하지 않았으며 내가 올바르게 수행하는지 확실하지 않습니다.


답변:


111
git log master..branch --oneline | tail -1

여기서 "branch"는 특정 지점 이름입니다. 점-점은 브랜치에 마스터가없는 커밋을 모두 제공합니다. tail -1이전 출력에서 ​​마지막 줄을 반환합니다.


3
이것은`branch``가 존재하는 경우에만 작동합니다. 분기가 삭제되면 어떻게 하시겠습니까?
Oz123

2
@ Oz123 분기는 HEAD 또는 sha1 또는 태그와 같은 모든 참조로 대체 될 수 있습니다. 그러나 분명히 당신은 일종의 참조가 필요합니다.
Zitrax

3
내가 기대했던 것을 제공하지 않습니다. 내 브랜치 (이전 브랜치)는 이미 마스터로 다시 병합되었습니다. 이는 xxx의 모든 커밋이 이미 마스터에 있음을 의미합니다. 그래도-어떤 커밋이 해당 브랜치의 첫 번째 커밋인지 알아야합니다. 또는 실제로는 해당 브랜치의 커밋 기록 만 조사해야합니다. 마스터에 있는지 여부는 상관 없습니다.
Motti Shneor

1
@MottiShneor는 병합 방법에 따라 까다로울 수 있습니다. 빨리 감기를 수행 한 경우 분기가 존재하지 않는 것처럼 보입니다. 그렇지 않으면 분기점을 찾는 여러 가지 방법이 나열된 이 답변에 관심 있을 수 있습니다 . 분기 지점이 있으면 SHA가을 대체 할 수 master있으며 분기가 삭제되지 않은 한 git log <sha>..branch --oneline | tail -1여전히 원하는 결과를 제공해야합니다.
ND Geek

1
당신이 사용할 수있는 --reverse등 색상으로 뒤로 로그를 읽고
도미니크

8

merge-base이 문제를 정확히 해결하도록 설계된 기능을 사용해야합니다 .

git merge-base remotes/origin/<branch> develop 

원래 분기점으로 돌아가고 싶다면 이것이 작동하지 않을 것이라고 생각합니다. 개발을 <branch>로 병합하면 병합 기반이 원래 분기점보다 더 새롭습니다.
Alexander Mills

5
또한 이것은 F를 가리키는 것이 아니라 마스터 브랜치의 커밋을 가리킬 것입니다 (OP의 그림에서는보기 어렵지만 B 또는 C 인 것 같습니다).
RomainValeri


1

브랜치 (이전 브랜치)가 다시 마스터로 병합되어 예상 결과가 나오지 않으면 python 스크립트를 사용하여 초기 브랜치 커밋 ID를 찾습니다.

git rev-list --first-parent changeset

--first-parent 는 병합 커밋을 볼 때 첫 번째 부모 커밋 만 따릅니다.

상위 분기를 찾을 때까지 위의 명령에서 변경 집합을 반복합니다.

def status_check(exec_command, exec_dir=None, background=False):
    if exec_dir:
        os.chdir(exec_dir)
    res = subprocess.Popen(exec_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if not background:
        result = res.communicate()
    return result



def findNewBranchCommits(changeset=None):
    cmd = "git rev-list --first-parent "+ changeset
    rev_list = status_check(cmd,self.module_dir)
    rev_list = str(rev_list[0]).split('\n')
    rev_list = list(filter(None, rev_list))
    for x in rev_list:                      # Iterate until branch base point
        rev_cmd = "git branch --contains " + x
        rev_cmd = status_check(rev_cmd,self.module_dir)
        rev_cmd = str(rev_cmd[0]).split('\n')
        if(len(rev_cmd) > 2): 
            print "First Commit in xxx branch",x
            break

findNewBranchCommits(changeset)

0
git cherry master -v | tail -1   

그러나 이것은 마스터에없는 xxx 브랜치에 대한 첫 번째 커밋 만 제공하고 xxx 브랜치에 대한 첫 번째 커밋은 제공하지 않습니다. 후자는 xxx 분기가 삭제 및 / 또는 한 번 이상 다시 생성 된 경우 어려울 수 있습니다. 이 경우 다음을 시도해 볼 수 있습니다.

git reflog | grep checkout | grep xxx | tail -1   

3
head -n 1대신 쓰려고 했습니까 tail -1? tail -1첫 번째 대신 가장 최근의 커밋을 반환합니다.
Nelu

0

이 명령을 시도했지만 작동했습니다.

git log <source_branch> <feature_branch> --oneline | tail -1

-1

git rev-list --ancestry-path $(git merge-base master xxx)..xxx | tail -1


내 저장소에서 이것은 xxx 분기의 첫 번째 커밋이 아니라 마스터에서 분기 xxx 로의 마지막 병합 이후 첫 번째 커밋을 보여줍니다.
jk7
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.