programing

Git에서 다음 커밋을 찾으려면 어떻게 해야 합니까? (참조인의 자녀/자녀)

telecom 2023. 6. 4. 10:18
반응형

Git에서 다음 커밋을 찾으려면 어떻게 해야 합니까? (참조인의 자녀/자녀)

ref^ 앞에 있는 .ref다음에 커밋을 받는 것은 어떻습니까? ref?

를 들어, 내가 를들어내, 가예.git checkout 12345다음 커밋을 확인하려면 어떻게 해야 합니까?

예, Git은 DAG 노드 포인터 구조 트리입니다.이 커밋 이후 커밋을 어떻게 찾습니까?

모든 커밋을 나열하려면 현재 커밋부터 시작하여 해당 하위 커밋 등을 나열합니다. 기본적으로 표준 git 로그이지만 시간이 지남에 따라 다음과 같은 것을 사용합니다.

git log --reverse --ancestry-path 894e8b4e93d8f3^..master

여기서 894e8b4e93d8f3는 표시하려는 첫 번째 커밋입니다.

N.b. DOS 명령 프롬프트를 사용하는 경우 캐럿에서 이스케이프해야 합니다.

git log --reverse --ancestry-path 894e8b4e93d8f3^^..master

허드슨(현재의 젠킨스)의 창작자인 가와구치 고스케는 2013년 11월에 출판했습니다: 고스케 / git-children-of:

커밋이 주어지면 해당 커밋의 직계 하위 항목을 찾습니다.

#!/bin/bash -e
# given a commit, find immediate children of that commit.
for arg in "$@"; do
  for commit in $(git rev-parse $arg^0); do
    for child in $(git log --format='%H %P' --all | grep -F " $commit" | cut -f1 -d' '); do
      git describe $child
    done
  done
done

스레드에서 알 수 있듯이 DAG(방향 비순환 그래프)로 표시되는 기록을 기반으로 하는 VCS에는 "하나의 부모" 또는 "하나의 자식"이 없습니다.

        C1 -> C2 -> C3
      /               \
A -> B                  E -> F
      \               /
        D1 -> D2 ----/

커밋 순서는 "토포 순서" 또는 "날짜 순서"에 의해 수행됩니다(GitPro 책 참조).

그러나 Git 1.6.0 이후에는 커밋의 하위 항목을 나열할 수 있습니다.

git rev-list --children
git log --children

참고: 상위 커밋의 경우 접미사와 동일한 문제가 있습니다.^해당 커밋 개체의 첫 번째 부모를 의미하는 수정 매개 변수로 이동합니다. ^<n>을 의미합니다.<n> 부모즉),rev^는 와동합다니등다에 합니다.rev^1).

이 지점에 .foo "그고이슈리이"를합니다.git merge bar그 때에foo첫 번째 부모가 됩니다.
예: 첫 번째 부모는 병합할 때 있었던 분기이고, 두 번째 부모는 병합한 분기에 대한 커밋입니다.

git rev-list --ancestry-path commit1..commit2

나는 설정commit1 및 재속약로대로.commit2헤드에 를 생성하는 모든 합니다.commit1그리고.commit2.

은 출의마줄다자식다니입음의 입니다.commit1으로 가는 에)commit2).

무슨 말인지 알겠어요.이전 커밋으로 이동하기 위한 풍부한 구문이 있지만 다음 커밋으로 이동하기 위한 구문은 없습니다.복잡한 역사에서 "다음 커밋은 무엇인가"라는 문제는 다소 어려워지지만, 복잡한 역사에서 '이전' 커밋과 동일한 경도의 병합이 발생합니다.단순한 경우, 선형 기록(일부 제한된 수의 커밋에 대해서만 로컬로)이 있는 단일 분기 내에서 앞으로 이동하거나 뒤로 이동하는 것이 좋습니다.

하지만 이것의 진짜 문제는 아이들의 커밋이 참조되지 않는다는 것입니다. 단지 거꾸로 연결된 목록일 뿐입니다.아동 커밋을 찾는 데는 검색이 필요한데, 이는 그리 나쁘지 않지만, Git이 refspec 논리에 넣고 싶어하는 것은 아닐 것입니다.

어쨌든, 저는 이 질문을 하게 되었습니다. 왜냐하면 저는 단지 한 번에 한 사람씩 앞으로 나아가기를 원하기 때문입니다. 시험을 하면서 말이죠. 그리고 때때로 여러분은 뒤로 물러서지 않고 앞으로 나아가야 합니다.저는 좀 더 생각해보고 다음과 같은 해결책을 생각해냈습니다.

현재 위치보다 먼저 커밋을 선택합니다.이건 아마 지점장일 거예요10번 지점~10번 지점~9번 'git checkout branch~8번 지점~7번 지점' 등 다음에 오는 곳은 'git checkout branch~7번 지점' 등입니다.

필요한 경우 스크립트에서 숫자를 줄이는 것은 매우 쉬울 것입니다.Git rev 목록을 구문 분석하는 것보다 훨씬 쉽습니다.

Git의 모든 내부 화살표는 원웨이로, 뒤를 가리킵니다.따라서 앞으로 나아가기 위한 짧고 편리한 구문은 없습니다. 단지 불가능할 뿐입니다.

"화살표를 거슬러 이동"하는 은 가능하지만, 이전에 본 적이 없다면 그 방법은 놀랍고, 이후에는 분명합니다.예를 들어 다음과 같습니다.

A <-B <-C <-D <-E   <-- last
        ^
        |
         \--------- middle

용사를 합니다.middle~2화살표를 두 번 따라갑니다.C로 돌아가다.A그럼 어떻게 해야 할까요?CD는 답은다음같다에서 시작합니다.E이을사용라는 last그리고 우리가 도착할 때까지 거꾸로 일을 합니다.middle우리가 방문하는 지점들을 기록하는 것.그러면 우리는 그냥 원하는 방향으로 이동합니다.last로 옮기다D 두 에서 한두사까지E.

지점이 있을 때는 특히 중요합니다.

          D--E   <-- feature1
         /
...--B--C   <-- master
         \
          F--G   <-- feature2

어느 커밋이 한 단계 후에Cfeature__ 방향으로 질문에 추가하기 전까지는 정답이 없습니다(빈칸에 입력).

이의커밋열방법는거하 사이의 것.C(외外)C그를 들어 ) 그자와체면, 말자하,면,G사용:

git rev-list --topo-order --ancestry-path master..feature2

--topo-order복잡한 분기 및 분기가 존재하는 경우에도 커밋이 토폴로지적으로 일치하는 순서로 수행되도록 합니다.이것은 체인이 선형이 아닌 경우에만 필요합니다.--ancestry-path제약은 우리가 거꾸로 일할 때를 의미합니다.feature2합니다.C그들 자신의 조상 중 한 명으로서.즉, 그래프(또는 그래프의 관련 청크)가 실제로 다음과 같이 표시되는 경우:

A--B--C   <-- master
 \     \
  \     F--G--J   <-- feature2
   \         /
    H-------I   <-- feature3

그러면 양식에 대한 간단한 요청이 있습니다.feature2..master커밋을 합니다.J,G그리고.I,그리고.F그리고.H어떤 순서로와 함께--ancestry-path는 녹아웃을 합니다.H그리고.I▁of의 후손이 .C 인뿐의A.와 함께--topo-order실제 열거 순서는 다음과 같습니다.J,그리고나서G,그리고나서F.

git rev-list명령은 이러한 해시 ID를 한 줄에 하나씩 표준 출력으로 내보냅니다.다음의 방향으로 한 발짝 앞으로 나아가기 위해feature2그럼, 우리는 그저 마지막 줄을 원합니다.

추가는그것다니 (그리고 수 )를 추가하는 --reverse 그 록도하록git rev-list커밋을 생성한 후 역순으로 커밋을 인쇄합니다.이 방법은 효과가 있지만 다음과 같은 파이프라인에서 사용할 경우:

git rev-list --topo-order --ancestry-path --reverse <id1>...<id2> | head -1

"을 얻기 , 긴 인 단의 "id2" 방로 "id2" 을밋 커음얻 " 그지매 " 리고긴 " 우밋커 " 는것목 " 록으다 " 향▁commit" " 커22고 " 긴매, 목밋록 ",git rev-list명령어가 쓰기를 시도할 때 손상된 파이프를 가져올 수 있습니다.head입력 읽기를 중지하고 종료했습니다.파손된 파이프 오류는 일반적으로 셸에 의해 무시되기 때문에, 이것이 작동합니다.사용할 때 무시되는지 확인하십시오.

추가하는 것도 매력적입니다.-n 1에▁git rev-list 명령, 께와 --reverse! 하지! 그것 에.git rev-list걸음 뒤로 물러난 후 중지하고 방문한 커밋 목록을 반대로 표시합니다.그래서 이것은 단지 생산합니다.<id2>매회

중요한 참고 사항

"다이아몬드" 또는 "벤젠 링" 그래프 조각은 다음과 같습니다.

       I--J
      /    \
...--H      M--...  <-- last
      \    /
       K--L

"로으을 "에서 "하나 H으로.last당신도 얻을 것입니다. I 또는 K그것에 대해 당신이 할 수 있는 것은 아무것도 없습니다. 두 커밋 모두 한 걸음 앞으로 나아가는 것입니다!그런 다음 결과 커밋에서 시작하여 다른 단계로 이동하면 이제 시작한 경로에 따라 커밋됩니다.

이를 위한 치료법은 한 번에 한 단계씩 이동하여 경로 종속 사슬에 갇히는 것을 피하는 것입니다.대신, 다른 작업을 수행하기 전에 전체 조상 경로 체인을 방문할 계획이라면 체인에 있는 모든 커밋의 전체 목록을 작성합니다.

git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits

그런 다음 이 목록의 각 커밋을 한 번에 하나씩 방문하면 전체 체인이 표시됩니다.--topo-order반드시 때릴 것입니다.I-그리고-J 그순대로서, 리고그,.K-그리고-L(K-L 쌍 이전에 I-J 쌍을 할지 이후에 할지 쉽게 예측할 수 있는 방법은 없지만) 그 순서대로입니다.

두 가지 실질적인 답변:

원 차일드

@Michael의 대답을 토대로, 나는 해킹을 했습니다.child 내명에 .gitconfig.

기본 케이스에서 예상대로 작동하며 다용도로 사용할 수도 있습니다.

# Get the child commit of the current commit.
# Use $1 instead of 'HEAD' if given. Use $2 instead of curent branch if given.
child = "!bash -c 'git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:\"$(git rev-parse --abbrev-ref HEAD)\"} | head -1' -"

기본적으로 현재 분기의 끝을 향해 한 단계씩 조상을 따라감으로써 HEAD의 자식에게 (다른 커밋-ish 인수가 주어지지 않는 한) 기본값을 줍니다(다른 커밋-ish 인수가 두 번째 인수로 주어지지 않는 한).

사용하다%h%H간단한 해시 형식을 사용하려면 다음과 같이 하십시오.

다중 자녀

HEAD가 분리된 경우(분기가 없음) 또는 분기에 관계없이 모든 자식을 가져오려면:

# For the current (or specified) commit-ish, get the all children, print the first child 
children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $1' -"

변할내용을 합니다.$1$*모든 아이들을 인쇄합니다.

변할수있다니습도경다를 변경할 .--all해당 커밋의 조상인 자녀만 표시하는 커밋(즉, 주어진 커밋의 "방향으로" 자녀만 표시하는 커밋).이렇게 하면 많은 어린이에서 한 명으로 출력을 좁힐 수 있습니다.

특정 "대상" 커밋을 염두에 두고 있지 않지만 분기에 있을 수 있는 하위 커밋을 보려는 경우 다음 명령을 사용할 수 있습니다.

git rev-list --children --all | grep ^${COMMIT}

모든 아이들과 손주들을 보고 싶다면, 당신은 사용해야 합니다.rev-list --children재귀적으로, 다음과 같이:

git rev-list --children --all | \
egrep ^\($(git rev-list --children --all | \
           grep ^${COMMIT} | \
           sed 's/ /|/g')\)

(손주에게만 제공되는 버전은 더 복잡한 것을 사용할 것입니다.sed 및/는cut.)

마지막으로, 당신은 그것을 공급할 수 있습니다.log --graph다음과 같이 트리 구조를 확인하는 명령:

git log --graph --oneline --decorate \
\^${COMMIT}^@ \
$(git rev-list --children --all | \
  egrep ^\($(git rev-list --children --all | \
             grep ^${COMMIT} | \
             sed 's/ /|/g')\))

참고: 위의 명령은 모두 셸 변수를 설정했다고 가정합니다.${COMMIT}관심 있는 자녀가 있는 커밋의 일부 참조(키워드, 태그, sha1).

저는 여러 가지 해결책을 시도해 보았지만 아무 것도 효과가 없었습니다.저는 제 것을 생각해 내야 했습니다.

다음 커밋 찾기

function n() {
    git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}

이전 커밋 찾기

function p() {
    git checkout HEAD^1
}

는 이 을 이별이있다니습칭에 가지고 있습니다.~/.gitconfig

first-child = "!f() { git log  --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; }; f"

터미널:

$ git log --format='%H %P' --all --reflog | grep -F " [commit-hash]" | cut -f1 -d' '

또는 .gitconfig 섹션 [alias]에서 다음을 수행합니다.

children = "!f() { git log --format='%H %P' --all --reflog | grep -F \" $1\" | cut -f1 -d' '; }; f"

분기에 에는 자식커모특분있경우는기에를 할 수 .gitk --all commit^..여기서 "commit"은 커밋을 식별하는 것입니다. 값이 에는 예를들, 커의약어 SHA-1 시이이값 c6661c5면다를 합니다.gitk --all c6661c5^..

Gitk의 "SHA1 ID:" 셀에 전체 SHA-1 해시 값을 입력해야 합니다. 값이 합니다. 이 에서는 "SHA-1 해시 값"을 수 있습니다.git rev-parse c6661c5.

에대신,git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d'이 약속의 모든 자녀를 포함하는 선을 생성합니다. 아마도 관련된 분기가 있는지 여부에 관계없이.

다음은 현재 HEAD의 모든 자식 목록을 별도의 행으로 표시합니다.

git rev-list --parents --all | awk -v h="$(git rev-parse HEAD)" 'index($0,h)>1{print$1}'

HEAD를 부모로 하는 모든 커밋을 출력합니다.

속도를 조금 더 낼 수 있습니다.^HEAD 앞에|그러면 HEAD의 조상들은 검색되지 않을 것입니다.

다른 커밋 또는 분기의 하위 항목을 인쇄하려면 해당 항목을 다음 위치에 놓습니다.HEAD 다 더 으로)HEAD장소).

저는 다음과 같은 방법으로 다음 아이를 찾을 수 있었습니다.

git log --reverse --children -n1 HEAD (where 'n' is the number of children to show)

기존 답변에서는 원하는 커밋이 포함된 분기가 있다고 가정합니다.

제 경우, 어떤 지점에도 포함되어 있지 않기 때문에 제가 찾던 커밋이 없었습니다.

나는 결국 끝까지 훑어보았습니다.gitk --reflog수동으로

reflog에서도 커밋을 찾을 수 없는 경우 다음 중 하나를 시도합니다.

  • git fsck --full 매달리는 커밋(즉, 어떤 분기에도 없는)을 나열하거나,
  • git fsck --lost-found 매달리는 것을 가리키는 참조를 만드는 것은 다른 답변에 기술을 적용하는 것을 약속합니다.

각 커밋은 병합(표준) 커밋의 경우 상위(상위)에 대한 포인터를 저장합니다.

따라서 부모로부터 자식 커밋(있는 경우)을 가리키는 방법은 없습니다.

라이브 코딩 세션을 구동하기 위해 Git 커밋 사용에서 Tomas Lycken의 응답은 커밋 스택의 끝에 잘 정의된 태그를 만들 수 있는 깔끔한 방법을 보여줍니다.본질적으로

git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'

여기서 "transmit-end"는 마지막 태그입니다.

다음 커밋을 신속하게 확인할 명령이 필요했습니다.
저는 결국 다음과 같은 별명을 갖게 되었습니다.

[alias]
next = "!f() { CMIT=$(git log --ancestry-path --format=%H ${commit}..${1} | tail -1) && git checkout $CMIT; }; f"

다음과 같이 통과할 분기를 지정해야 합니다.

git next master

에 추가할 수 있습니다..gitconfig파일을 직접 편집합니다.

출력의 예:

~/home/myRepo | dd9e66ee  git next master
Previous HEAD position was dd9e66e Update README
HEAD is now at d71c74b Rename project; update to JUnit5

이 명령을 실행하면 당연히 분리된 헤드 모드로 전환됩니다. :)

다음 아이는 다음과 같은 방법으로 거절합니다.

git rev-list --children --reverse b3443a2^.. | sed -n 1p | awk '{print $2}'
  1. HEAD에 대한 특정 커밋의 자녀가 있는 참조 목록을 역순으로 가져옵니다.
  2. 첫 번째 줄 사용
  3. 다음 하위 참조를 인쇄합니다.

언급URL : https://stackoverflow.com/questions/2263674/how-do-i-find-the-next-commit-in-git-child-children-of-ref

반응형