개발관련/Git

Git 브랜치의 가장 가까운 부모를 찾는 방법

Rateye 2021. 10. 19. 11:31
728x90
반응형
질문 : Git 브랜치의 가장 가까운 부모를 찾는 방법은 무엇입니까?

다음과 같은 커밋 트리가있는 다음 로컬 저장소가 있다고 가정 해 보겠습니다.

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

master 는 내 최신 안정 릴리스 코드 이고 develop'다음'릴리스 코드 이며 featuredevelop 준비중인 새로운 기능 입니다.

후크를 사용하여 원격 리포지토리에서 할 수 있기를 원하는 것은 f develop HEAD의 직접적인 자손이 feature 이 거부되는 것입니다. d git rebase 되었기 때문에 커밋 트리는 다음과 같습니다.

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

따라서 다음을 수행 할 수 있습니다.

  • feature 의 상위 분기를 식별 하시겠습니까?
  • f 가 자손 인 상위 브랜치에서 커밋을 식별합니까?

거기에서 부모 브랜치의 HEAD가 무엇인지 확인하고 f 선행자가 부모 브랜치 HEAD와 일치하는지 확인하여 기능을 리베이스해야하는지 결정합니다.

답변

원격 저장소에 개발 브랜치의 복사본이 있다고 가정하면 (초기 설명은 로컬 저장소에 설명되어 있지만 원격에도 존재하는 것처럼 들립니다) 원하는 것을 얻을 수 있지만 접근 방식은 당신이 상상했던 것과는 조금 다릅니다.

Git의 기록은 커밋 의 DAG를 기반으로합니다. 분기 (및 일반적으로 "ref")는 지속적으로 증가하는 커밋 DAG에서 특정 커밋을 가리키는 일시적인 레이블입니다. 따라서 분기 간의 관계는 시간이 지남에 따라 달라질 수 있지만 커밋 간의 관계는 그렇지 않습니다.

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

baz 가 (이전 버전의) bar 기반으로 한 것 같습니다. 그러나 우리는 삭제하는 경우 bar ?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

baz foo 기반 인 것처럼 보입니다. baz 의 조상은 변경되지 않았으며 레이블 (및 결과 매달린 커밋)을 제거했습니다. 4 새 레이블을 추가하면 어떻게 될까요?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

baz quux 기반으로하는 것처럼 보입니다. 그래도 조상은 바뀌지 않았고 레이블 만 바뀌 었습니다.

그러나 만약 우리가“커밋 6 이 커밋 3 의 후손인가?”라고 묻는다면 36 이 완전한 SHA-1 커밋 이름이라고 가정하면 barquux 레이블이 있는지 여부에 관계없이 대답은 "예"입니다.

따라서 "푸시 된 커밋이 개발 브랜치의 현재 팁의 후손입니까?"와 같은 질문을 할 수 있지만 "푸시 된 커밋의 상위 브랜치가 무엇입니까?"라고 안정적으로 질문 할 수 없습니다.

당신이 원하는 것에 가까워지는 가장 신뢰할 수있는 질문은 다음과 같습니다.

모두를 위해 부모로서 개발의 현재의 팁을 가지고, (현재 개발의 팁과 조상을 제외)의 조상 커밋 밀어 :

  • 그러한 커밋이 하나 이상 존재합니까?
  • 그러한 모든 커밋은 단일 부모 커밋입니까?

다음과 같이 구현할 수 있습니다.

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

이것은 당신이 제한하고 싶은 것 중 일부를 다룰 것이지만 전부는 아닐 수도 있습니다.

참고로 다음은 확장 된 예제 기록입니다.

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \
                        R---S

H' , J , K 또는 N 을 수락하면서 HS 를 거부하는 데 사용할 수 LP 도 허용합니다 (병합이 포함되지만 개발 팁을 병합하지 않음).

LP 도 거부하려면 질문을 변경하고

푸시 된 모든 커밋의 조상 (현재 개발 팁 및 조상 제외) :

  • 두 부모와의 커밋이 있습니까?
  • 그렇지 않다면 적어도 하나의 그러한 커밋이 (유일한) 부모 를 개발하는 현재 팁을 가지고 있습니까?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac
출처 : https://stackoverflow.com/questions/3161204/how-to-find-the-nearest-parent-of-a-git-branch

 

728x90
반응형