질문 : Git 브랜치의 가장 가까운 부모를 찾는 방법은 무엇입니까?
다음과 같은 커밋 트리가있는 다음 로컬 저장소가 있다고 가정 해 보겠습니다.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
는 내 최신 안정 릴리스 코드 이고 develop
은 '다음'릴리스 코드 이며 feature
은 develop
준비중인 새로운 기능 입니다.
후크를 사용하여 원격 리포지토리에서 할 수 있기를 원하는 것은 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
의 후손인가?”라고 묻는다면 3
과 6
이 완전한 SHA-1 커밋 이름이라고 가정하면 bar
및 quux
레이블이 있는지 여부에 관계없이 대답은 "예"입니다.
따라서 "푸시 된 커밋이 개발 브랜치의 현재 팁의 후손입니까?"와 같은 질문을 할 수 있지만 "푸시 된 커밋의 상위 브랜치가 무엇입니까?"라고 안정적으로 질문 할 수 없습니다.
당신이 원하는 것에 가까워지는 가장 신뢰할 수있는 질문은 다음과 같습니다.
모두를 위해 부모로서 개발의 현재의 팁을 가지고, (현재 개발의 팁과 조상을 제외)의 조상 커밋 밀어 :
- 그러한 커밋이 하나 이상 존재합니까?
- 그러한 모든 커밋은 단일 부모 커밋입니까?
다음과 같이 구현할 수 있습니다.
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
을 수락하면서 H
및 S
를 거부하는 데 사용할 수 L
및 P
도 허용합니다 (병합이 포함되지만 개발 팁을 병합하지 않음).
L
및 P
도 거부하려면 질문을 변경하고
푸시 된 모든 커밋의 조상 (현재 개발 팁 및 조상 제외) :
- 두 부모와의 커밋이 있습니까?
- 그렇지 않다면 적어도 하나의 그러한 커밋이 (유일한) 부모 를 개발하는 현재 팁을 가지고 있습니까?
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
'개발관련 > Git' 카테고리의 다른 글
터미널에 Git 트리를 표시 할 수 없을 때 (0) | 2021.10.20 |
---|---|
분기가 지정되지 않은 "git push"의 기본 동작 (0) | 2021.10.20 |
변경 사항을 잃지 않고 마지막 푸시되지 않은 git 커밋을 해제하는 방법 (0) | 2021.10.19 |
마스터에서 Git 분기 업데이트 (0) | 2021.10.19 |
Git에서 마지막 커밋을 해제하는 방법 (0) | 2021.10.19 |