Git을 사용하여 하나의 특정 브랜치에 * 오직 * 존재하는 모든 커밋을 표시하고 * 아무 ** 다른 브랜치에는 표시하지 않습니다.


87

분기가 주어지면 해당 분기 에만 존재하는 커밋 목록을보고 싶습니다 . 에서 이 질문에 우리는 한 지점에 있지만 그 이상의 다른 지점을 지정하지 않은 한 어떤 커밋을 참조하는 방법에 대해 설명합니다.

이것은 약간 다릅니다. 나는 1 분기에 있지만에있는 커밋보고 싶은 어떤 다른 지점.

유스 케이스는 일부 분기가 병합되어야하고 직접 커밋되지 않아야하는 분기 전략에 있습니다. 이것은 "병합 전용"브랜치에서 직접 커밋이 이루어 졌는지 확인하는 데 사용됩니다.

편집 : 아래는 테스트 할 더미 git repo를 설정하는 단계입니다.

git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt 
git commit -am "2nd valid commit on master"
git checkout merge-only 
git merge master

병합 전용 브랜치에서 직접 작성된 "병합 전용에서 직접 잘못된 커밋"메시지가있는 커밋 만 표시되어야합니다.


1
이 질문은 병합 된 모든 분기가 현재 저장소에서 사용 가능하고 완전히 병합 된 후에는 삭제되지 않으며 빨리 감기와 병합되지 않을 수도 있다고 가정합니다. 내가 뭔가를 놓친다면 알려주세요. 그러나 이것은 비교적 작은 허용 된 merge-from 브랜치 세트에서만 작동하는 것 같습니다. 그래서 git log ^branch1 ^branch2 merge-only-branch구문을 사용하지 않는 이유는 무엇입니까?
Karl Bielefeldt

1
git log ^branch1 ^branch2 merge-only-branch모든 단일 지점을 나열해야합니다. bash / grep을 영리하게 사용하면 피할 수 있지만 (아래 답변 참조) git이 이에 대한 기본 지원을 제공하기를 바랍니다. 모든 병합 지점이 원격이라고 가정하는 것이 맞습니다 (로컬 만 다른 개발자에게는 존재하지 않는 것만 큼 좋습니다). 를 사용하면 --no-merges병합 된 후 원래 병합에서 분기가 삭제 된 모든 커밋이 생략되므로 병합 전용 분기가 비 병합 전용 분기 (예 : 마스터)에 병합 될 때까지 유지된다고 가정합니다.
jimmyorr 2011

답변:


76

우아한 솔루션을 찾았습니다.

git log --first-parent --no-merges

물론 귀하의 예에서는 초기 커밋이 여전히 표시됩니다.

이 답변은 초기 커밋이 여전히 나타나기 때문에 질문에 정확히 대답하지 않습니다. 다른 한편으로 여기에 오는 많은 사람들은 그들이 찾고있는 답을 찾는 것 같습니다.


1
마스터에 대한 초기 커밋이 여전히 표시되므로 질문에 대한 답변이 아닙니다.
jimmyorr

6
이것만으로는 "해당 분기에만 존재하는 커밋" 조건을 충족하지 못합니다 . 및 분기의 initial valid commit일부인을 표시합니다 . 그러나 현재 브랜치 이름을 끝에 붙여서 현재 브랜치의 유래를 알고있는 ^ 접두사가 붙은 브랜치 이름을 입력하면 문제의 절반 (병합 된 것 제외)이 해결됩니다. 예 :merge-onlymastergit log --first-parent --no-merges merge-only ^master
Slipp D. Thompson 2013

14
나는 이것이 왜 그렇게 많은 찬성표를 받았는지 확실하지 않으며, 질문과 전혀 관련이없는 것 같습니다. 포스터가 찾고 있던 정보를 확실히 제공하지 않습니다.
Chris Rasys 2014 년

2
이 대답은 완벽하지 않을 수 있습니다. 그러나 그것은 간단하고 확실히 일부까지 작동합니다. 나는 분기 이름을 추가하는 것이 유용하다는 것을 알았습니다. 즉, 모든 커밋이 주어진 분기에 속하는 필터 :git log --first-parent --no-merges | grep <branch_name>
artm

1
감사합니다. 최고의 솔루션 imo.
Jakub Keller

29

내 친애하는 친구 Redmumba의 의례 :

git log --no-merges origin/merge-only \
    --not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
    grep -Fv refs/remotes/origin/merge-only)

... origin/merge-only원격 병합 전용 분기 이름은 어디에 있습니까 ? 로컬 전용 자식의 repo, 대체 작업을하는 경우 refs/remotes/originrefs/heads, 그리고 대체 원격 지사 이름 origin/merge-only지역 지점 이름 merge-only, 즉 :

git log --no-merges merge-only \
    --not $(git for-each-ref --format="%(refname)" refs/heads |
    grep -Fv refs/heads/merge-only)

2
다른 사람이 git 만 사용하여 grep-less 솔루션을 제공 할 수 있기를 바라지 만 그렇지 않은 경우 꽤 우아하게 느껴집니다.
jimmyorr 2011

1
예, 우아합니다. 사용은 git for-each-ref기원의 모든 심판 이름을 나열하고, grep -v병합 전용 지점을 생략 할 수 있습니다. 모든 참조 목록 (병합 전용 분기 제외)을 전달 git log하는 --not옵션을 받습니다 . 문제에 대한보다 우아한 대답이 있다면 들어 보겠습니다.
jimmyorr 2011

2
오, 가장 우아한 대답이라고 확신합니다. 나는 그것이 진정한 우아함을 위해 약간 "단어 / 복잡함"이라고 주장하고있다. :-) 당신의 접근 방식을 폄하하려는 것이 아닙니다!
Chris K

1
명령 의 후행 /*git for-each-refs일부 기존 파일과 일치하지 않고 설정 failglob하거나 갖지 않는 것에 의존합니다 nullglob( bash 옵션, 다른 쉘은 다양 함). 별표를 따옴표 / 이스케이프하거나 후행을 그대로 두어야합니다 /*( git for-each-ref패턴은 "처음부터 슬래시까지"와 일치 할 수 있음). grep -Fv refs/remotes/origin/foo( refs/heads/foo)를 사용 하여 어떤 참조가 제거되는지 더 엄격하게 할 수 있습니다.
Chris Johnsen 2011

3
다른 브랜치가 아닌 한 브랜치에있는 커밋 만보고 싶은 경우 단순화 할 수 있습니다. git log --no-merges B1 --not B2여기서 B1은 관심있는 브랜치이고 B2는 B1을 비교할 브랜치입니다. B1과 B2는 모두 로컬 또는 원격 분기 일 수 있으므로을 지정 git log --no-merges master --not origin/master하거나 두 개의 원격 분기를 지정할 수도 있습니다.
mr.b

21
git log origin/dev..HEAD

그러면 브랜치에서 이루어진 모든 커밋이 표시됩니다.


2
@Prakash origin/branchName는 원격 브랜치의 헤드를 HEAD가리키고 해당 브랜치의 마지막 로컬 커밋의 commitid를 가리 킵니다. 따라서 git push를 사용하면 작동하지 않습니다.
Bharat

이것을 사용하여 다른 로컬 브랜치를 비교할 수 있습니다. --no-merges 플래그는 OP의 원래 질문을 해결하는 데 유용 할 수도 있습니다.
Paul Whipp

15

@Prakash 답변이 작동합니다. 명확성을 위해 ...

git checkout feature-branch
git log master..HEAD

기능 분기에 대한 커밋을 나열하지만 업스트림 분기 (일반적으로 마스터)는 나열하지 않습니다.



7

이 시도:

git rev-list --all --not $(git rev-list --all ^branch)

기본적으로 git rev-list --all ^branch분기에없는 모든 개정을 가져온 다음 저장소의 모든 개정을 가져오고 분기 에만 있는 개정 인 이전 목록을 뺍니다 .

@Brian의 댓글 이후 :

git rev-list의 문서에서 :

List commits that are reachable by following the parent links from the given commit(s)

따라서 git rev-list AA가 커밋 인 경우 와 같은 명령 은 A를 포함하여 A에서 도달 할 수있는 커밋을 나열합니다.

이를 염두에두고

git rev-list --all ^A

A에서 도달 할 수없는 커밋을 나열합니다.

따라서 git rev-list --all ^branch분기 끝에서 도달 할 수없는 모든 커밋을 나열합니다. 이것은 분기의 모든 커밋을 제거하거나 다른 분기에만있는 커밋을 제거합니다.

이제 가자 git rev-list --all --not $(git rev-list --all ^branch)

이것은 git rev-list --all --not {commits only in other branches}

그래서 우리 all는 도달 할 수없는 목록 을 원합니다.all commits only in other branches

분기 에만있는 커밋 집합입니다 . 간단한 예를 들어 보겠습니다.

             master

             |

A------------B

  \

   \

    C--------D--------E

                      |

                      branch

여기서 목표는 다른 브랜치에없는 커밋 인 D와 E를 얻는 것입니다.

git rev-list --all ^branch B 만 주다

자, git rev-list --all --not B우리가 내려 오는 것입니다. 또한 git rev-list -all ^BB에서 도달 할 수없는 모든 커밋을 원합니다. 우리의 경우 D와 E입니다. 이것이 우리가 원하는 것입니다.

이것이 명령이 올바르게 작동하는 방법을 설명하기를 바랍니다.

댓글 후 수정 :

git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt 
git commit -am "2nd valid commit on master"

위의 단계 후에, 당신이한다면 당신은 git rev-list --all --not $(git rev-list --all ^merge-only)당신이 찾고 있던 커밋을 얻을 "bad commit directly on merge-only"것입니다.

그러나 단계의 마지막 단계를 수행 git merge master하면 명령이 예상 된 출력을 제공하지 않습니다. 현재 마스터의 추가 커밋도 병합 전용으로 병합되었으므로 병합 전용에없는 커밋이 없기 때문입니다. 그래서 git rev-list --all ^branch빈 결과를 제공하고, 따라서 git rev-list -all --not $(git rev-list --all ^branch)줄 것이다 모든 병합 만에 커밋.


1
흠 ... 이유는 확실하지 않지만 작동하지 않습니다. xargs -L 1 -t git branch -a --contains많은 오탐 (실제로 다른 분기에있는 커밋) 을 표시 하도록 명령의 출력을 파이핑합니다 . 나는 --no-merges. 그래도 답변 해 주셔서 감사합니다!
jimmyorr 2011

더미 git repo에서 볼 수있는 한 나를 위해 잘 작동하는 것 같습니다.
manojlds 2011

답변에 대한 문제를 설명하는 데 도움이되는 더미 git 저장소를 만드는 단계를 추가했습니다.
jimmyorr 2011

아, 이런. 내가 완전히 생각하기 전에 이것을 찬성했습니다. git rev-list --all ^branch에없는 모든 커밋을 제공합니다 branch. 그런 다음 목록에서 해당 뺀되어 있습니다 에를 branch; 그러나 정의에 branch따라에 있지 않은 모든 커밋은에 있지 않으므로 branch아무것도 빼지 않습니다. jimmyorr가 찾고있는 것은에 branch있지만 master다른 브랜치에 있지 않은 커밋입니다 . 포함되지 않은 커밋을 빼고 싶지 않습니다 branch. 다른 분기에있는 커밋을 빼고 싶습니다.
Brian Campbell

1
@manojlds "(모든 개정)-(분기에없는 모든 개정) = 분기에 개정." 예, 모든 수정본을에서 가져 오는 데 작동 branch하지만 git rev-list branch. 당신은 git rev-list branch더 복잡하고 느린 방식으로 글을 쓰고 있습니다. branch 다른 브랜치에없는 모든 커밋을 찾는 방법 인 질문에 대답하는 것은 작동하지 않습니다 .
Brian Campbell

2

허용되는 답변의 또 다른 변형은 master

git log origin/master --not $(git branch -a | grep -Fv master)

마스터 이외의 분기에서 발생하는 모든 커밋을 필터링합니다.


1

이것은 정확한 답은 아니지만 서식에 대한 액세스와 많은 공간이 필요합니다. : 나는 가장 멋진 두 답변을 고려할 것을 뒤에 이론을 설명하려고합니다 수락 한(가) (현재 적어도) 하나를 최고 순위를 . 그러나 사실 그들은 다른 질문에 답 합니다.

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 JK. 우리는 커밋 보여주는 끝날 것이다 I, 또한 커밋 H, G, F, 등 병합 커밋하고 모두에서 시작하여 연결할 수에-없음 이들의 M뒤로 작업 만 방문 첫째 각 병합 커밋에게의 부모를.

가장 인기있는 답변은 예를 들어 병합 전용 분기가 될 master시기를 보는 데 매우 적합합니다 master. 모든 "실제 작업"이 이후에에 병합 된 사이드 브랜치에서 수행 되었다면 다음 master과 같은 패턴을 갖게됩니다.

I---------M---------N   <-- master
 \       / \       /
  o--o--o   o--o--o

모든 않은 레터라는 곳 o커밋은 보통 (비 병합) 커밋하고 있습니다 MN병합 커밋이다. 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 loggit 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 loggit 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수락 된 답변에서 사용 된 명령 줄 인수 의 접두사 는 그래프의 일부 부분을 처음부터 전혀 방문하지 않도록 억제 합니다.

우리는 이러한 기능을 사용하여 두 가지 질문에 대해 원하는 답을 얻습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.