이것은 정확한 답은 아니지만 서식에 대한 액세스와 많은 공간이 필요합니다. : 나는 가장 멋진 두 답변을 고려할 것을 뒤에 이론을 설명하려고합니다 수락 한 과 (가) (현재 적어도) 하나를 최고 순위를 . 그러나 사실 그들은 다른 질문에 답 합니다.
Git의 커밋은 한 번에 둘 이상의 브랜치에 "on"되는 경우가 많습니다. 실제로 그것이 질문의 내용 중 상당 부분입니다. 주어진:
...--F--G--H <-- master
\
I--J <-- develop
대문자가 실제 Git 해시 ID를 나타내는 경우 출력 에서 커밋 만 검색 하거나 커밋 만H 찾습니다 . 커밋 은 두 가지 모두 에 있으므로 제외하고 싶습니다.I-Jgit logG
(이와 같이 그려진 그래프에서 새로운 커밋은 오른쪽에 있습니다. 이름 은 해당 줄에서 가장 오른쪽에있는 하나의 커밋을 선택합니다. 각 커밋에는 부모 커밋이 있으며 이는 왼쪽에 커밋 H입니다. G, 그리고 부모 J입니다 I.의 부모 I입니다 G. 다시의 부모 G입니다 F, 그리고 F단순히 여기에 표시되지 않도록 부모가 있습니다의 그것의 일부 ...섹션).
이 특히 간단한 경우에는 다음을 사용할 수 있습니다.
git log master..develop # note: two dots
볼 I-J, 또는 :
git log develop..master # note: two dots
보기 H전용입니다. 두 개의 점 뒤에있는 오른쪽 이름은 Git에 다음 과 같이 알려줍니다. yes, these commits . 두 점 앞에있는 왼쪽 이름은 Git에 다음과 같이 알려줍니다. no, not these commits . Git은 마지막 ( 커밋 H또는 커밋) 에서 시작하여 거꾸로J 작동 합니다 . 이에 대한 (많은) 자세한 내용은 Think Like (a) Git를 참조 하십시오 .
원래의 질문이 표현되는 방식은 동일한 일반 범주의 다른 이름이 아닌 특정 이름 에서 도달 할 수 있는 커밋을 찾는 것 입니다. 즉, 더 복잡한 그래프가있는 경우 :
O--P <-- name5
/
N <-- name4
/
...--F--G--H--I---M <-- name1
\ /
J-----K <-- name2
\
L <-- name3
우리는 이러한 이름 중 하나를 골라 수 name4또는를 name3하고 질문 하는 커밋 그 이름에 의해 발견 아닌 다른 이름의가 될 수 있는가? 우리가 선택 name3하면 답은 commit L입니다. 를 선택 name4하면 답은 전혀 커밋이 아닙니다. name4이름은 커밋 N이지만 커밋 N은 at에서 시작 name5하고 거꾸로 작업 하여 찾을 수 있습니다 .
허용되는 답변은 분기 이름이 아닌 원격 추적 이름으로 작동하며 철자가 지정된 origin/merge-only이름을 선택한 이름으로 지정하고 해당 네임 스페이스의 다른 모든 이름을 볼 수 있습니다. 또한 병합 표시를 방지합니다. name1"관심있는 이름"으로 선택하고 다른 이름이 아닌 다른 이름 에서 연결할 수있는 커밋 표시name1 라고 말하면 병합 커밋 M과 일반 커밋을 볼 수 I있습니다.
가장 인기있는 답변은 상당히 다릅니다. 그것은 그래프를 저지 통과에 대해 전부 없이 다음 두 다리 및 병합을 표시하지 않고 커밋의 입니다 병합. name1예를 들어로 시작하면 표시되지 않지만 M(병합) merge의 첫 번째 부모 M가 commit 이라고 가정하면 Icommit J및 K. 우리는 커밋 보여주는 끝날 것이다 I, 또한 커밋 H, G, F, 등 병합 커밋하고 모두에서 시작하여 연결할 수에-없음 이들의 M뒤로 작업 만 방문 첫째 각 병합 커밋에게의 부모를.
가장 인기있는 답변은 예를 들어 병합 전용 분기가 될 master시기를 보는 데 매우 적합합니다 master. 모든 "실제 작업"이 이후에에 병합 된 사이드 브랜치에서 수행 되었다면 다음 master과 같은 패턴을 갖게됩니다.
I---------M---------N <-- master
\ / \ /
o--o--o o--o--o
모든 않은 레터라는 곳 o커밋은 보통 (비 병합) 커밋하고 있습니다 M및 N병합 커밋이다. Commit I은 최초의 커밋 입니다. 최초의 커밋이며 마스터에 있어야 하는 유일한 커밋은 병합 커밋이 아닙니다. 이 이외의git log --first-parent --no-merges master 커밋 이 표시 되면 다음 과 같은 상황이 발생합니다. I
I---------M----*----N <-- master
\ / \ /
o--o--o o--o--o
일부 기능 브랜치를 병합하는 것이 아니라에서 *직접 만든 커밋을보고 싶습니다 master.
요컨대, 인기있는 답변은 master언제 master병합 전용인지를 확인하는 데 적합하지만 다른 상황에는 적합하지 않습니다. 허용되는 답변은 이러한 다른 상황에서도 작동합니다.
원격 추적 이름이 origin/master 분기 이름 과 같 습니까?
Git의 일부는 그렇지 않다고 말합니다.
git checkout master
...
git status
라고 on branch master하지만 :
git checkout origin/master
...
git status
말한다 HEAD detached at origin/master. 나는 동의하는 것을 선호합니다 git checkout/ git switch: 당신이 그것에 "on"할 수 없기 때문에 지점 이름origin/master 이 아닙니다 .
허용되는 대답 은 원격 추적 이름 origin/*을 "분기 이름"으로 사용합니다.
git log --no-merges origin/merge-only \
--not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
grep -Fv refs/remotes/origin/merge-only)
을 호출하는 중간 줄은 git for-each-ref라는 원격지의 원격 추적 이름을 반복합니다 origin.
이 원래 문제에 대한 좋은 솔루션입니다 이유는 우리가 여기에 관심이 있다는 것입니다 다른 사람의 것이 아니라, 지점 이름을 우리 지점 이름. 그러나 그것은 우리가 브랜치 이름이 아닌 다른 것으로 브랜치 를 정의했음을 의미 합니다 . 괜찮습니다. 당신이 이것을 할 때 당신이 이것을하고 있다는 것을 인식하십시오.
git log 커밋 그래프의 일부를 순회합니다.
우리가 정말이라는 것을 일련의 여기에 대한 있습니다 검색하는 무엇 daglets가 : 참조 정확하게 우리는 "지점"이란 무엇을 의미합니까? 즉, 전체 커밋 그래프의 일부 하위 집합 내 에서 조각을 찾고 있습니다.
Git이와 같은 브랜치 이름 master, 같은 태그 이름 v2.1또는 같은 원격 추적 이름을 볼 때마다 Git origin/master이 해당 커밋 과 해당 커밋에서 얻을 수있는 모든 커밋 에 대해 알려주는 경향이 있습니다. , 거꾸로 작업.
수학에서는 이것을 그래프 걷기 라고합니다 . Git의 커밋 그래프는 Directed Acyclic Graph 또는 DAG 이며 이러한 종류의 그래프는 특히 걷기에 적합합니다. 이러한 그래프를 걸을 때 사용중인 경로를 통해 도달 할 수있는 각 그래프 정점을 방문하게 됩니다. Git 그래프의 정점은 커밋이며 가장자리는 각 자식에서 각 부모로가는 호 (단방향 링크)입니다. (이것은 Think Like (a) Git 이 들어오는 곳입니다. arcs의 단방향 특성은 Git이 자식에서 부모로 거꾸로 작동해야 함을 의미합니다.)
그래프 워킹을위한 두 가지 주요 Git 명령은 git log및 git rev-list. 이러한 명령은 매우 유사합니다. 사실 대부분은 동일한 소스 파일에서 빌드되지만 출력은 다릅니다. git log사람이 읽을 수있는 git rev-list출력 을 생성하고 다른 Git 프로그램이 읽을 수있는 출력 을 생성합니다. 1 두 명령 모두 이런 종류의 그래프 걷기를 수행합니다.
그들이하는 그래프 워크는 구체적으로 : 몇 가지 시작점 커밋 세트 (아마도 하나의 커밋, 아마도 해시 ID 묶음, 아마도 해시 ID로 확인되는 이름 묶음)가 주어지면 그래프를 살펴보고 커밋을 방문 합니다. --not또는 접두사 ^, 또는 --ancestry-path, 또는와 같은 특정 지시문 은 어떤 방식 으로든 그래프 워크 를 --first-parent수정합니다 .
그래프 워크를 할 때 각 커밋을 방문합니다. 하지만 워킹 된 커밋 중 일부만 선택된 부분 만 인쇄 합니다. 또는 같은 지시문 은 인쇄 를 커밋하는 그래프 걷기 코드를 알려줍니다 .--no-merges--before <date>
이 방문을 수행하기 위해 한 번에 하나의 커밋을 수행하기 위해이 두 명령은 우선 순위 대기열을 사용합니다 . 실행 git log하거나 git rev-list시작점 커밋을 제공합니다. 그들은 이러한 커밋을 우선 순위 대기열에 넣습니다. 예를 들어, 간단한 :
git log master
이름 master을 원시 해시 ID로 바꾸고 해당 해시 ID를 큐에 넣습니다. 또는:
git log master develop
두 이름을 모두 해시 ID로 바꾸고 (두 개의 다른 해시 ID라고 가정하면) 둘 다 대기열에 넣습니다.
이 큐의 커밋 우선 순위는 더 많은 인수에 의해 결정됩니다. 예를 들어, 인수 --author-date-order는 커미터 타임 스탬프가 아닌 작성자 타임 스탬프 를 사용 git log하거나 알려줍니다 . 기본값은 커미터 타임 스탬프를 사용하고 날짜 별 최신 커밋 (숫자 날짜가 가장 높은 커밋)을 선택하는 것입니다. 따라서 두 개의 서로 다른 커밋에 대한 확인이 있다고 가정하면 Git은 나중에 먼저 오는 커밋을 표시 합니다.git rev-listmaster develop
어쨌든 개정 워킹 코드는 이제 루프에서 실행됩니다.
- 큐에 커밋이있는 동안 :
- 첫 번째 대기열 항목을 제거합니다.
- 이 커밋을 인쇄할지 여부를 결정하십시오. 예를 들어
--no-merges: 병합 커밋이면 아무것도 인쇄하지 않습니다. --before: 날짜가 지정된 시간 이전에 오지 않으면 아무것도 인쇄하지 않습니다. 인쇄 가 억제 되지 않으면 커밋을 인쇄합니다. for git log, 해당 로그를 표시합니다. 의 경우 git rev-list해시 ID를 인쇄합니다.
- 이 커밋의 부모 커밋 중 일부 또는 전부를 대기열에 넣습니다 (현재 존재하지 않고 이미 방문하지 않은 경우 2 ). 일반적인 기본값은 모든 부모를 넣는 것입니다. 를 사용하면 각 병합
--first-parent의 첫 번째 부모를 제외하고 모두 억제됩니다 .
(모두 git log와 git rev-list할 수있는 역사의 단순화를 하거나하지 않고 다시 작성 부모 뿐만 아니라이 시점에서, 그러나 우리는 여기에 건너 수 있습니다.)
병합 커밋이 없을 때 시작하고 HEAD뒤로 작업하는 것과 같은 간단한 체인의 경우 큐에는 항상 루프 맨 위에 하나의 커밋이 있습니다. 하나의 커밋이 있으므로 그것을 꺼내 인쇄하고 (단일) 부모를 대기열에 넣고 다시 돌아 다니며 첫 번째 커밋에 도달하거나 사용자가 git log출력에 지쳐서 종료 할 때까지 체인을 거꾸로 따릅니다. 프로그램. 이 경우 순서 옵션은 중요하지 않습니다. 표시 할 커밋이 하나뿐입니다.
병합이 있고 우리가 두 부모 (병합의 "다리"모두)를 따를 때 git log또는 git rev-list하나 이상의 시작 커밋 을 제공 할 때 정렬 옵션이 중요합니다.
마지막 으로 커밋 지정자 의 효과 --not또는 ^앞에 있는 것을 고려하십시오 . 이를 작성하는 방법에는 여러 가지가 있습니다.
git log master --not develop
또는:
git log ^develop master
또는:
git log develop..master
모두 같은 의미입니다. 두 개 이상의 이름에 적용된다는 점을 제외 --not하면 접두사와 비슷합니다 ^.
git log ^branch1 ^branch2 branch3
수단 하지 BRANCH1하지 브랜치, 브랜치 예; 그러나:
git log --not branch1 branch2 branch3
branch1이 아니라 branch2가 아니라 branch3을 의미 하며,--not 이를 끄려면 두 번째 를 사용해야합니다 .
git log --not branch1 branch2 --not branch3
조금 어색합니다. 두 개의 "not"지시문은 XOR을 통해 결합되므로 원하는 경우 다음과 같이 작성할 수 있습니다.
git log --not branch1 branch2 ^branch3
난독 화 하려면 branch1이 아니라 branch2, yes branch3 을 의미 합니다.
이것들은 모두 그래프 워크에 영향을 주어 작동합니다. 로 git log또는 git rev-list그래프를 걸어, 그것은 확실하게 하지 어떤 그가 어떤에서 접근 커밋 큐 우선 순위에 넣어 부정 참조. (사실, 이들은 시작 설정에도 영향을 미칩니다. 부정 된 커밋은 명령 줄에서 바로 우선 순위 대기열로 이동할 수 없으므로 git log master ^master예를 들어 아무것도 표시하지 않습니다.)
gitrevisions 문서에 설명 된 모든 멋진 구문 이 이것을 사용하며 git rev-parse. 예를 들면 :
$ git rev-parse origin/pu...origin/master # note: three dots
b34789c0b0d3b137f0bb516b417bd8d75e0cb306
fc307aa3771ece59e174157510c6db6f0d4b40ec
^b34789c0b0d3b137f0bb516b417bd8d75e0cb306
점 3 개 구문은 왼쪽 또는 오른쪽에서 연결할 수있는 커밋을 의미 하지만 둘 다에서 연결할 수있는 커밋은 제외합니다 . 이 경우 origin/master커밋 b34789c0b은 자체적으로 origin/pu( fc307aa37...) 에서 도달 할 수 있으므로 origin/master해시가 한 번 부정과 함께 두 번 표시되지만 실제로 Git은 두 개의 양의 참조 (부정되지 않은 두 개의 해시 ID)를 입력하여 3 점 구문을 달성합니다. ^접두사로 표시되는 하나의 음수 .
유사하게 :
$ git rev-parse master^^@
2c42fb76531f4565b5434e46102e6d85a0861738
2f0a093dd640e0dad0b261dae2427f2541b5426c
^@구문 수단은 모두 소정의 부모 커밋 및 master^자체 - 상기 브랜치는 이름에 의해 선택된 커밋 제 부모 master는 부모 두 가지도록, 병합 커밋 -is. 이들은 두 부모입니다. 과:
$ git rev-parse master^^!
0b07eecf6ed9334f09d6624732a4af2da03e38eb
^2c42fb76531f4565b5434e46102e6d85a0861738
^2f0a093dd640e0dad0b261dae2427f2541b5426c
^!접미사 수단 자체를 저지 없지만, 부모 중 어느 것도 . 이 경우 master^입니다 0b07eecf6.... 우리는 이미 ^@접미사 가있는 두 부모를 보았습니다 . 여기 그들은 다시 있지만 이번에는 부정되었습니다.
1 많은 Git 프로그램은 말 그대로 git rev-list다양한 옵션으로 실행 되고 출력을 읽고 사용할 커밋 및 / 또는 기타 Git 개체를 파악합니다.
2 그래프가 비순환 이기 때문에, 제약 조건을 추가하면 모든 자식 을 우선 순위에 표시하기 전에 부모를 표시하지 않으므로 이미 방문한 적이 없음을 보장 할 수 있습니다 . --date-order, --author-date-order및 --topo-order이 제약 조건을 추가하십시오. 이름이없는 기본 정렬 순서는 그렇지 않습니다. 커밋 타임 스탬프가 엉망인 경우 (예를 들어 시계가 꺼진 컴퓨터에 의해 일부 커밋이 "미래에"수행 된 경우) 경우에 따라 출력이 이상하게 보일 수 있습니다.
여기까지왔다면 이제 git log
요약:
git log 그래프의 일부 또는 전체를 걷는 동안 선택한 커밋을 표시하는 것입니다.
--no-merges모두 받아 들여 현재 상위권 답변에서 발견 인수, 일부 커밋 보여주는 억압 이다는 걸었다.
--first-parent현재 최상위 순위 답변 의 인수 는 그래프 걷기 자체 중에 그래프의 일부를 걷는 것을 억제 합니다.
--not수락 된 답변에서 사용 된 명령 줄 인수 의 접두사 는 그래프의 일부 부분을 처음부터 전혀 방문하지 않도록 억제 합니다.
우리는 이러한 기능을 사용하여 두 가지 질문에 대해 원하는 답을 얻습니다.
git log ^branch1 ^branch2 merge-only-branch구문을 사용하지 않는 이유는 무엇입니까?