ref^
전에 커밋을 참조 ref
하십시오. 커밋 후에는 ref
어떻습니까?
예를 들어 git checkout 12345
다음 커밋을 어떻게 확인합니까?
감사.
추신 : git은 DAG 노드 포인터 구조체 트리입니다. 이 커밋 후에 커밋을 어떻게 찾습니까?
git children-of
" 도 참조하십시오 !
ref^
전에 커밋을 참조 ref
하십시오. 커밋 후에는 ref
어떻습니까?
예를 들어 git checkout 12345
다음 커밋을 어떻게 확인합니까?
감사.
추신 : git은 DAG 노드 포인터 구조체 트리입니다. 이 커밋 후에 커밋을 어떻게 찾습니까?
git children-of
" 도 참조하십시오 !
답변:
현재 커밋에서 시작하여 커밋을 모두 나열하려면 기본적으로 표준 git log이지만 시간이 지남에 따라 다음과 같은 것을 사용하십시오.
git log --reverse --ancestry-path 894e8b4e93d8f3^..master
여기서 894e8b4e93d8f3은 표시하려는 첫 번째 커밋입니다.
HEAD^
하십시오 894e8b4e93d8f3^
.
...
, ^..
자동으로 실패
fatal: unrecognized argument: --ancestry-path
자식 버전 1.7.1에 도착
Hudson (현재 Jenkins) Kohsuke Kawaguchi 의 제작자가 방금 게시 (2013 년 11 월) :
kohsuke / 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 (Directed Acyclic Graph)로 표시되는 히스토리를 기반으로하는 VCS 에는 "하나의 부모"또는 "하나의 자식"이 없습니다.
C1 -> C2 -> C3
/ \
A -> B E -> F
\ /
D1 -> D2 ----/
커밋 순서는 "topo-order"또는 "date-order"에 의해 수행됩니다 ( GitPro book 참조 ).
그러나 Git1.6.0 부터 커밋의 자식을 나열 할 수 있습니다.
git rev-list --children
git log --children
참고 : 부모 커밋의 경우 동일한 커밋이 있으며 해당 커밋 객체 ^
의 첫 번째 부모를 의미하는 개정 매개 변수 의 접미어 가 있습니다. ^<n>
는 <n>
부모를 의미합니다 (즉, rev^
에 해당 rev^1
).
지점에 foo
있고 " git merge bar
"를 발행 foo
하면 첫 번째 부모가됩니다.
즉 : 첫 번째 부모는 병합 할 때 있었던 지점이고 두 번째 부모는 병합 한 지점의 커밋입니다.
git rev-list --children
확실히 내가 원하는 것처럼 보이지만 DWIM은 아닙니다. 모든 부모와 자녀를 나열하는 것으로 보입니다. 나는 그것들을 모두 나열하고 그들을 통해 파싱 할 수 있다고 가정합니다 ... bleh,하지만 그 무언가.
git rev-list --children
단지 아이를 나열하는 것이 아니라 부모 상장 자녀와 함께 ... 당신은 항상 구문 분석 할 필요가있다.
$ git children0of 9dd5932
fatal: No annotated tags can describe '71d7b5dd89d241072a0a078ff2c7dfec05d52e1f'.
However, there were unannotated tags: try --tags.
어떤 결과를 얻습니까?
git-children-of
는 git describe 를 사용 하여 SHA를 사람이 읽을 수있는 형식으로 만들려고 시도하는데 @TomHale의 오류로 실패 할 수 있으며 v1.0.4-14-g2414721
SHA를 예상하면 혼란 스러울 수 있습니다. 간단한 것으로 교체 echo
하면 훌륭한 도구입니다. 감사합니다!
내가 찾은 것은
git rev-list --ancestry-path commit1..commit2
내가 설정 한 경우 commit1
현재는 커밋하고 commit2
현재의 머리. 이것은 나에게 사이의 경로 구축 모든 커밋의 목록 반환 commit1
및 commit2
.
출력의 마지막 행은 commit1의 자식입니다 (commit2의 경로에 있음).
| tail -1
아이를 얻기 위해 추가하십시오 .
무슨 뜻인지 알아 이전 커밋으로가는 구문이 풍부하지만 다음 커밋으로 이동하는 것은 실망 스럽습니다. 복잡한 역사에서 "다음 커밋은 무엇인가"라는 문제가 다소 어려워 지지만 복잡한 병합에서는 동일한 경도가 '이전'커밋과 함께 나타납니다. 간단한 경우, 선형 히스토리가있는 단일 분기 (일부 제한적 커밋의 경우 로컬조차도)에서는 앞뒤로 이동하는 것이 좋습니다.
그러나 이것의 실제 문제는 자식 커밋이 참조되지 않고 역방향으로 연결된 목록이라는 것입니다. 자식 커밋을 찾는 것은 너무 나쁘지 않지만 git이 refspec 로직에 넣고 싶지 않은 검색을 필요로합니다.
어쨌든, 나는이 질문에 도달했습니다. 왜냐하면 나는 한 번에 한 번의 커밋을 수행하고 테스트를 수행하기를 원하기 때문에 때로는 뒤로 물러서지 않고 앞으로 나아가 야하기 때문입니다. 글쎄, 좀 더 생각하면이 솔루션을 생각해 냈습니다.
현재 위치보다 먼저 커밋을 선택하십시오. 아마도 브랜치 헤드 일 수 있습니다. 분기 ~ 10에 있다면 "git checkout branch ~ 9"다음 "git checkout branch ~ 8"다음에 다음을 얻으려면 "git checkout branch ~ 7"등입니다.
필요한 경우 스크립트에서 숫자를 줄이는 것이 정말 쉬워야합니다. git rev-list를 파싱하는 것보다 훨씬 쉽습니다.
BRANCH=master; git co $BRANCH~$[ $(git rev-list HEAD..$BRANCH | wc -l) - 1 ]
"당신은 가지를 향해 가지 않으면 안됩니다.
@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의 자식 (다른 커밋이 필요한 인수가 제공되지 않은 경우)을 제공하는 것이 기본값입니다.
짧은 해시 양식을 원한다면 %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의 히스토리는 한 줄이 아닌 DAG이므로 많은 커밋에는 공통 부모 (분기)가있을 수 있으며, 커밋에는 둘 이상의 부모 (병합)가있을 수 있습니다.
특정 분기를 염두에두면 로그를보고 현재 커밋을 상위로 나열하는 커밋을 확인할 수 있습니다.
<rev>^
"parent commit"(병합 커밋의 '첫 번째 부모')입니다.
특정 "대상"이없는 경우에는 마음에 커밋 대신에있을 수 있습니다 자식 커밋보고 싶은 어떤 지점 것은,이 명령을 사용할 수 있습니다 :
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}
를 관심있는 커밋의 참조 (branch, tag, sha1)로 설정했다고 가정합니다 .
${COMMIT}
지속되지 않지만 $(git rev-parse HEAD)
대신 사용할 수 있습니다
${COMMIT}
.
(이것은 중복 질문에 대한 답변으로 시작되었습니다. 정리하기 위해 약간의 가벼운 편집을했습니다.)
Git의 모든 내부 화살표는 한 방향이며 뒤로 향합니다. 따라서 앞으로 나아갈 수있는 편리한 구문이 없습니다. 단지 불가능합니다.
그것은 이다 당신이 나중에 전에 그것을 본 후 분명하지 않은 경우 "화살표에 대한 이동"하지만 놀라운을 할 수있는 방법으로 가능. 우리가 가지고 있다고 가정 해 봅시다.
A <-B <-C <-D <-E <-- last
^
|
\--------- middle
를 사용 middle~2
하여 화살표를 C
뒤로 두 번 따라 갑니다 A
. 그래서 우리는 어떻게에서 이동합니까 C
에 D
? 대답은 : 우리가 시작하는 E
이름을 사용하여, last
우리가 얻을 때까지, 작업의 뒤로 middle
, 우리가 길을 따라 방문하는 점을 기록 . 그런 다음 우리는 원하는 방향으로 last
움직 입니다 . 한 단계는로 이동 D
하거나 두 단계는로 이동 합니다 E
.
분기가있을 때 특히 중요합니다.
D--E <-- feature1
/
...--B--C <-- master
\
F--G <-- feature2
어느 커밋이 한 단계 뒤에 C
있습니까? 질문에 추가하기 전까지는 정답이 없습니다 : feature 방향으로 (공백을 채우십시오).
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
: 그들은의 후손 없습니다 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 방향의 다음 커밋"을 얻으려면 커밋 목록이 매우 길기 때문에 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
. 그것에 대해 당신이 할 수있는 일은 없습니다 : 두 커밋 모두 한 단계 앞으로입니다! 결과 커밋에서 시작하여 다른 단계로 넘어 가면 이제 시작한 경로에 전념하게됩니다.
이를위한 치료법은 한 번에 한 단계 씩 이동하고 경로 종속 체인에 고정되지 않도록하는 것입니다. 당신이 전체 가계 경로 체인을 방문 할 계획이라면 대신, 다른 작업을 수행하기 전에 , a를 체인에있는 모든 커밋의 목록을 :
git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits
그런 다음이 목록의 각 커밋을 한 번에 하나씩 방문하면 전체 체인을 얻을 수 있습니다. 은 --topo-order
당신이 명중 있는지 확인합니다 I
- 및 - J
순서로, 그리고 K
- 및 - L
(당신은 KL 쌍 전이나 후에 IJ 쌍을 다하겠습니다 여부를 예측할 수있는 쉬운 방법은 없습니다하지만) 순으로.
이 별칭이 있습니다 ~/.gitconfig
first-child = "!f() { git log --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; }; f"
f()
입니까? 그리고 head -1
첫 아이가되어야합니다. 그렇지 않으면 단순히 HEAD를보고 할 것입니다.
f()
. 예, head -1
용감한 추측입니다.
nextref = "!f() { git log --reverse --ancestry-path --pretty=%H $1..HEAD | head -${2:-1} | tail -1; }; 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'
이 커밋의 모든 자식을 포함하는 라인을 생성 할 것입니다.
각 커밋은 부모에 대한 포인터를 저장합니다 (병합 (표준) 커밋의 경우 부모).
따라서 부모로부터 자식 커밋 (있는 경우)을 가리킬 수있는 방법이 없습니다.
이 게시물 ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 )은 다음과 같은 경우에 깔끔한 방법을 보여줍니다. 커밋 스택 끝에 잘 정의 된 태그를 만들 수 있습니다. 기본적
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
으로 "demo-end"가 마지막 태그입니다.
기존 답변은 찾고있는 커밋이 포함 된 분기가 있다고 가정합니다.
필자의 경우, 내가 찾은 커밋 git rev-list --all
에는 분기가 포함되어 있지 않았기 때문에 진행되지 않았습니다.
나는 gitk --reflog
수동으로 살펴 보았습니다.
reflog에서도 커밋을 찾을 수 없으면 다음 중 하나를 시도하십시오.
git fsck --full
매달려있는 (즉, 분기에없는) 커밋을 나열하거나git fsck --lost-found
매달려있는 커밋을 가리키는 심판을 다른 답변에 기술을 적용합니다.