programing

특정 분기에 대한 커밋만 가져오려면 로그를 Git합니다.

topblog 2023. 5. 23. 21:19
반응형

특정 분기에 대한 커밋만 가져오려면 로그를 Git합니다.

특정 분기의 일부인 모든 커밋을 나열하려고 합니다.

다음을 사용하면 분기의 모든 커밋과 상위(마스터)의 커밋이 나열됩니다.

git log mybranch

제가 찾은 또 다른 옵션은 마스터가 도달할 수 있는 커밋을 제외하고 원하는 것을 제공하는 것이지만 다른 지점 이름을 알 필요는 없습니다.

git log mybranch --not master

제가 사용하려고 했던 것입니다.git for-each-ref하지만 내 지점도 나열되어 있으므로 실제로는 모두 제외됩니다.

git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)

업데이트:

얼마 전에 찾은 새로운 옵션을 테스트하고 있는데, 지금까지 제가 찾고 있던 옵션은 다음과 같습니다.

git log --walk-reflogs mybranch

업데이트(2013-02-13T15:08):

--walk-reflogs 옵션은 좋지만, reflogs에 대한 만료가 있음을 확인했습니다(기본값 90일, gc.reflogExpire).

제가 찾던 답을 찾은 것 같습니다.

git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")

사용 가능한 분기 목록에서 현재 분기를 제거하고 해당 목록을 사용하여 로그에서 제외하는 중입니다.이렇게 하면 지점에서만 도달한 커밋만 받습니다.

당신이 사용해야 할 것처럼 들리는 것으로부터.cherry:

git cherry -v develop mybranch

여기에는 현재 개발 중이 아닌 지사 내에 포함된 모든 커밋이 표시됩니다.마지막 옵션( 분기)을 생략하면 현재 분기가 대신 비교됩니다.

VonC가 지적했듯이, 당신은 항상 당신의 브랜치를 다른 브랜치와 비교하기 때문에 당신의 브랜치를 알고 비교할 것을 선택하세요.

하지만 다른 지점 이름을 알 필요는 없습니다.

저는 이것이 가능하다고 생각하지 않습니다. Git의 분기는 "git diff가 충분히 보여주지 않는다"에서 설명한 것처럼 항상 다른 하나 또는 적어도 다른 커밋을 기반으로 합니다.

여기에 이미지 설명 입력

올바른 커밋을 표시하려면 로그의 참조 지점이 필요합니다.

"GIT - 제가 어디서 시작했나요?":

분기는 DAG의 특정 커밋에 대한 포인터일 뿐입니다.

그래서 만약에git log master..mybranch입니다. 만약에 "commit"이라고 한다면 커밋이 입니다. 여전히 너무 많은 커밋을 표시할 수 있습니다.mybranch을 으로 함myotherbranch그 는 에근한그자체거에 를 두고 .master.

해당 참조(분기의 오리진)를 찾으려면 다음과 같이 커밋을 구문 분석하고 해당 커밋이 어느 분기에 있는지 확인해야 합니다.

저는 마침내 OP가 원하는 것을 할 수 있는 방법을 찾았습니다.다음과 같이 간단합니다.

git log --graph [branchname] 

git log --graph origin/[branchname] # if your local checkout isn't up to date

명령은 제공된 분기에서 연결할 수 있는 모든 커밋을 그래프 형식으로 표시합니다. 해당 의 커밋을 수 *커밋 줄의 첫 번째 문자입니다.

를 들어예를들어살, ▁of▁excer의 발췌문을 살펴보도록 하겠습니다.git log --graph masterCakephp GitHubrepo는 다음과 같습니다.

D:\Web Folder\cakephp>git log --graph master
*   commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
|\  Merge: c3f45e8 0459a35
| | Author: José Lorenzo Rodríguez <lorenzo@users.noreply.github.com>
| | Date:   Tue Aug 30 08:01:59 2016 +0200
| |
| |     Merge pull request #9367 from cakephp/fewer-allocations
| |
| |     Do fewer allocations for simple default values.
| |
| * commit 0459a35689fec80bd8dca41e31d244a126d9e15e
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Mon Aug 29 22:21:16 2016 -0400
| |
| |     The action should only be defaulted when there are no patterns
| |
| |     Only default the action name when there is no default & no pattern
| |     defined.
| |
| * commit 80c123b9dbd1c1b3301ec1270adc6c07824aeb5c
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Sun Aug 28 22:35:20 2016 -0400
| |
| |     Do fewer allocations for simple default values.
| |
| |     Don't allocate arrays when we are only assigning a single array key
| |     value.
| |
* |   commit c3f45e811e4b49fe27624b57c3eb8f4721a4323b
|\ \  Merge: 10e5734 43178fd
| |/  Author: Mark Story <mark@mark-story.com>
|/|   Date:   Mon Aug 29 22:15:30 2016 -0400
| |
| |       Merge pull request #9322 from cakephp/add-email-assertions
| |
| |       Add email assertions trait
| |
| * commit 43178fd55d7ef9a42706279fa275bb783063cf34
| | Author: Jad Bitar <jadbitar@mac.com>
| | Date:   Mon Aug 29 17:43:29 2016 -0400
| |
| |     Fix `@since` in new files docblocks
| |

커밋은 다시시커밋만만 .8314c2ff833280bbc7102cb6d4fcf62240cd3ac4그리고.c3f45e811e4b49fe27624b57c3eb8f4721a4323b다가 나다*커밋 라인의 첫 번째 문자입니다.이러한 커밋은 마스터 분기에서 생성된 것이고 나머지 4개는 다른 분기에서 생성된 것입니다.

다음 명령을 사용합니다.

git shortlog --no-merges --graph --abbrev-commit master..<mybranch>

또는

git log --no-merges --oneline --decorate master..<mybranch>

다음 셸 명령은 사용자가 원하는 작업을 수행해야 합니다.

git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)

주의사항

가지고 계신다면,mybranch체크아웃하면 위의 명령이 작동하지 않습니다.그이는그이에 입니다.mybranch에 의해서도 도달할 수 있습니다.HEAD그래서 Git은 그 커밋이 유일하다고 생각하지 않습니다.mybranch다음 시간에 작동하도록 하기 위해mybranch체크아웃되어 . 또한 체아되다에 제외를 . 또한 다음에 대한 제외 항목을 추가해야 합니다.HEAD:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD \
    --all)

그러나, 당신은 제외하지 말아야 합니다.HEADmybranch체크아웃되지 않으면 에 배타적이지 않은 커밋을 표시할 위험이 있습니다.mybranch.

마가지이로지라는 이름의 이 있는 입니다.origin/mybranch의 그은지해니다당합에 해당합니다.mybranchbranch,그것을해야 할 입니다: 점은그, 당신제외야할해것다입니:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --all)

으로 "" " " " "에 대해서만 해당됨")origin/master), ), 을 제외해야 origin/HEAD또한:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

브랜치를 체크아웃한 상태에서 원격 브랜치가 있고 원격 저장소의 기본값이 원격 브랜치인 경우 많은 항목을 제외하게 됩니다.

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

설명.

git rev-list명령은 지정된 리비전을 실행하고 발생한 SHA1 식별자를 덤프하는 하위 수준(플럼핑) 명령입니다.와 동등하다고 생각합니다.git logSHA1만 표시됩니다. 로그 메시지, 작성자 이름, 타임스탬프, "멋진" 항목은 표시되지 않습니다.

--no-walk에서 알 있듯이 암것는시하처럼방은, 다니합지옵션름이서에,▁option다▁prevents를 방지합니다.git rev-list조상의 사슬을 걷는 것으로부터.그래서 입력하면,git rev-list --no-walk mybranch즉 " 하의나 SHA1 , ▁the▁tip▁of▁다▁the▁ofifier니▁will▁sha▁one"의 팁 커밋 식별자만 됩니다.mybranch분점.

--exclude=refs/heads/mybranch --all는 의이말니다줍해론다니를 말해줍니다.git rev-list다음을 제외한 각 참조에서 시작합니다.refs/heads/mybranch.

그래서, 당신이 달릴 때.git rev-list --no-walk --exclude=refs/heads/mybranch --all는 Git는다음을제외하각고참팁조의커밋대에한 SHA1식인다니합을 각합니다.refs/heads/mybranch이러한 커밋과 해당 커밋의 상위 항목은 사용자가 관심이 없는 커밋입니다. 이러한 커밋은 사용자가 보고 싶지 않은 커밋입니다.

다른 커밋은 당신이 보고 싶은 커밋입니다. 그래서 우리는 출력을 수집합니다.git rev-list --no-walk --exclude=refs/heads/mybranch --all그리고 Git에게 그 범죄들과 그들의 조상들을 제외한 모든 것을 보여달라고 말합니다.

--no-walk인수는 대규모 저장소에 필요하며 소규모 저장소에 대한 최적화입니다.이것이 없다면, Git는 인쇄해야 할 것이고, 셸은 필요 이상으로 많은 커밋 식별자를 수집(및 메모리에 저장)해야 할 것입니다.저장소가 크면 수집된 커밋 수가 셸의 명령줄 인수 제한을 쉽게 초과할 수 있습니다.

Git bug?

저는 다음과 같은 것들이 효과가 있을 것이라고 예상했습니다.

git log --all --not --exclude=refs/heads/mybranch --all

하지만 그렇지 않습니다.이건 Git의 버그라고 생각합니다만, 의도적인 것일 수도 있습니다.

빠른 답변:

git log $(git merge-base master b2)..HEAD

예를 들어,

  1. 마스터 분기가 있음

  2. 몇 가지 커밋 수행

  3. b2라는 분기를 만들었습니다.

  4. git log -n1와 mastercommitId 사이의 입니다.

  5. b2에서 몇 가지 커밋을 수행합니다.

  6. git log 및 됩니다.

  7. 커밋 범위를 사용하십시오. 개념에 익숙하지 않은 사용자는 구글로 검색하거나 오버플로를 쌓을 수 있습니다.

    실제 컨텍스트의 경우 예를 들어 다음과 같이 수행할 수 있습니다.

    git log commitID_FOO..comitID_BAR
    

    "."는 log 명령의 범위 연산자입니다.

    즉, 간단한 형식으로 커밋보다 최신 로그를 모두 제공합니다.ID_FOO...

  8. #4 지점, 병합 베이스를 보십시오.

    그래서:git log COMMITID_mergeBASE..HEAD.

  9. Git은 이렇게 병합 기반을 검색할 수 있습니다.

    git merge-base b2 master
    
  10. 마지막으로 다음을 수행할 수 있습니다.

    git log $(git merge-base master b2)..HEAD
    

다음과 같은 방법을 사용할 수 있습니다.

#!/bin/bash

all_but()
{
    target="$(git rev-parse $1)"
    echo "$target --not"
    git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
    while read entry
    do
        eval "$entry"

        test "$ref" != "$target" && echo "$ref"
    done
}

git log $(all_but $1)

또는 Git 사용자 설명서의 레시피에서 차용하면 다음과 같습니다.

#!/bin/bash
git log $1 --not $( git show-ref --heads | cut -d' ' -f2 | grep -v "^$1" )

저는 이 접근법이 비교적 쉽다고 생각했습니다.

지점에 체크아웃한 후

  1. 달려.

    git rev-list --simplify-by-decoration -2 HEAD
    

이렇게 하면 SHA가 두 개만 제공됩니다.

분기의 마지막 커밋 [C1]

분기의 첫 번째 커밋에 부모를 커밋합니다 [C2].

  1. 지금 실행

    git log --decorate --pretty=oneline --reverse --name-status <C2>..<C1>
    

여기서 C1과 C2는 첫 번째 명령을 실행할 때 얻을 수 있는 두 개의 문자열입니다.두 번째 명령에 <> 없이 이 값을 입력합니다.

분기 내 파일 변경 내역 목록이 표시됩니다.

git rev-list --exclude=master --branches --no-walk

그렇지 않은 모든 지점의 팁을 나열합니다.master.

git rev-list master --not $(git rev-list --exclude=master --branches --no-walk)

됩니다.master다른 지점의 역사에는 없는 역사입니다.

순서 지정은 커밋 선택을 위한 필터 파이프라인을 설정하는 옵션에서 중요합니다.--branches적용되어야 하는 배제 패턴을 따라야 합니다.--no-walk커밋 rev-list가 걷지 않도록 제공하는 필터를 따라야 합니다.

현재 분기에 대한 커밋을 출력합니다.인수가 전달되면 해시만 출력합니다.

git_show_all_dll_only_only_on_on_this_dll

#!/bin/bash
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF
  
  usage: $ME {NEWER_BRANCH} {OLDER_BRANCH} {VERBOSE}
  
  Compares 2 different branches, and lists the commits found only 
  in the first branch (newest branch). 

  e.g. 
  
  $ME         -> default. compares current branch to master
  $ME B1      -> compares branch B1 to master
  $ME B1 B2   -> compares branch B1 to B2
  $ME B1 B2 V -> compares branch B1 to B2, and displays commit messages
  
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show commit msgs if any arg passed for arg 3
if [ "$3" ]
then
  OPT="-v"
fi

# get branch names
OLDER_BRANCH=${2:-"master"}
if [ -z "$1" ]
then
  NEWER_BRANCH=$(git rev-parse --abbrev-ref HEAD)
else
  NEWER_BRANCH=$1
fi

if [ "$NEWER_BRANCH" == "$OLDER_BRANCH" ]
then
  echo "  Please supply 2 different branches to compare!"
  show_help
fi

OUT=$(\git cherry $OPT $OLDER_BRANCH $NEWER_BRANCH)

if [ -z "$OUT" ]
then
  echo "No differences found. The branches $NEWER_BRANCH and $OLDER_BRANCH are in sync."
  exit;
fi

if [ "$OPT" == "-v" ]
then
  echo "$OUT"
else
  echo "$OUT" | awk '{print $2}'
fi

여기서 저는 리처드 한센의 답변(및 벤 C의 제안)에 기초한 별칭을 제시하지만, 태그를 제외하도록 적응했습니다.별칭은 상당히 강력해야 합니다.

# For Git 1.22+
git config --global alias.only '!b=${1:-$(git branch --show-current)}; git log --oneline --graph "heads/$b" --not --exclude="$b" --branches --remotes #'
# For older Git:
git config --global alias.only '!b=${1:-$(git symbolic-ref -q --short HEAD)}; b=${b##heads/}; git log --oneline --graph "heads/$b" --not --exclude="$b" --branches --remotes #'

사용 예:

git only mybranch  # Show commits that are in mybranch ONLY
git only           # Show commits that are ONLY in current branch

지정된 분기가 삭제된 경우(태그의 영향 제외) 가비지 수집 후 손실되는 커밋만 의미합니다.안타깝게도 이름이 지정된 태그가 있더라도 별칭이 작동해야 합니다.mybranch에)heads/. 또한 ONLY의 정의에 따라 커밋이 원격 분기(있는 경우 업스트림 포함)의 일부인 경우 커밋이 표시되지 않습니다.

별칭은 선택한 커밋의 그래프로 한 줄 기록을 표시합니다.

  a --- b --- c --- master
   \           \
    \           d
     \           \
      e --- f --- g --- mybranch (HEAD)
       \
        h --- origin/other

, 위의예를들면보어,면,git only표시:

  * (mybranch,HEAD)
  * g
  |\
  | * d
  * f 

( 제외)HEAD의 Git에 와 같이 적용됨 별은이같습다니다음과칭경조같(Git의위우이와정됨전이조같정▁),(▁(됨▁the이▁becomes),)

git config --global alias.only '!b=${1:-$(git branch --show-current)};  git log --oneline --graph --all --not --exclude="refs/heads/$b" --exclude=HEAD --all #'

또는 HEAD를 포함한 모든 태그를 포함하는 변형(및 출력하지 않으므로 현재 분기를 기본값으로 제거):

git config --global alias.only '!git log --oneline --graph --all --not --exclude=\"refs/heads/$1\" --all #'

분기가 체크아웃되면 분기를 삭제할 수 없고 HEAD 또는 다른 태그가 지정한 커밋이 손실되지 않으므로 이 마지막 버전은 삭제된 커밋을 실제로 충족하는 유일한 버전입니다.그러나 처음 두 가지 변형이 더 유용합니다.

마지막으로 별칭은 원격 분기에서 작동하지 않습니다(예: git only origin/master를 들어 다음과 같습니다. 예:

git config --global alias.remote-only '!git log --oneline --graph "$1" --not --exclude="$1" --remotes --branches #'

옵션 1(더 빨라 보이지만 오류가 발생할 수 있음)bash: /mingw64/bin/git: Argument list too longGit Bash에서 (리눅스에서는 작동했지만) 프로젝트에 몇 개의 지점이 있는지에 따라 다릅니다.

git log <your_branch> --not $(git branch -a | grep -v <your_branch> | grep -ve '->' | sed "s/\s//g")

옵션 2

git rev-list <your_branch> | git name-rev --stdin | sed -E 's/~[0-9]+//g; s/\^[0-9]+//g' | grep " <your_branch>" | awk -F " " '{print $1}'

제 상황에서는 Git Flow와 GitHub를 사용하고 있습니다.이를 위해 필요한 것은 기능 분기를 GitHub의 개발 분기와 비교하는 것입니다.

기능 분기에 대한 커밋만 표시됩니다.

예:

https://github.com/your_repo/compare/develop ...feature_message_name

특정 분기에 대한 로그를 한 줄로 내보내야 했습니다.

그래서 저는 아마 더 간단한 해결책을 생각해 냈을 것입니다.
를 할 때.git log --pretty=oneline --graph 현재분서수않은모든커다밋다로 을 알 수 .|

그서간단한.grep -v작업 수행:
git log --pretty=oneline --graph | grep -v "^|"

물론 다른 정보가 필요한 경우 한 줄로 유지하는 즉시 예쁜 매개 변수를 변경할 수 있습니다.

병합 커밋도 제거할 수 있습니다.
가 " branch"로에 다른 "Merge branch"를 합니다.grep -v그리고 당신은 끝났습니다.

제 구체적인 경우, 최종 명령은 다음과 같습니다.
git log --pretty="%ad : %an, %s" --graph | grep -v "^|" | grep -v "Merge branch"

이것은 2021년에도 여전히 논의되었고 8년 전에 질문이 있었습니다.저는 왜 아무도 기트를 제안하지 않는지 혼란스럽습니다. 첫째 부모님.요즘은 그게 해결책 아닌가요?저는 현재 같은 문제를 겪고 있고 이것은 저에게 꽤 괜찮은 것 같습니다.다음 옵션을 결합했습니다.

git --first-parent --cherry  first-commit-on-branch..

마스터의 추가 커밋을 피쳐 브랜치에 병합하기도 했지만, 체리 픽, 오른쪽만 및 병합 없음의 조합인 체리 때문에 이러한 커밋이 필터링됩니다.분기의 첫 번째 커밋을 수동으로 찾거나 그 이후의 커밋을 모두 찾아야 합니다.

위의 의견에서 본 바에 따르면, 당신은 해당 커밋만 해당 분기에 속해 있고 부모에만 속해 있지 않기를 원합니다.그러나 다른 분기에서 분기를 만들 때 해당 커밋도 하위 분기에 복사됩니다.그러나 질문에 대해서는 다음 명령을 사용할 수 있습니다.

git log childBranch...parentBranch

상위 분기가 원격 분기인 경우 다음 명령을 사용할 수 있습니다.

git log yourBranch --not --remotes=origin

저는 그것을 사용하여 그럭저럭 합니다.git log <branch>또한 다음과 같은 옵션도 있습니다.--not <branch-name>원본 문서: git-log

형식이 포함된 예제:

git log branch-name  --date-order --format='%ai %an <%ae> %h %f'--format='%ai , %an ,<%ae> ,%h ,%f' >> c:\log.csv

단순히 "git logbranch"를 입력하고 현재 지점에 대한 모든 커밋을 가질 수 있도록 별칭을 만들었습니다.다음은 별칭입니다.

[alias]
    logbranch = "!cd -- \"${GIT_PREFIX:-.}\" && CURRENT_BRANCH=$(git branch --show-current) && git log $CURRENT_BRANCH --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v refs/heads/$CURRENT_BRANCH) #"

NB: 홈 디렉토리에 있는 .gitconfig 파일의 [alias] 태그 아래에 놓습니다.

그래서 저는 기본적으로 질문 게시물에 원래 게시된 내용을 사용하고 CURRENT_BRANCH 변수를 사용하여 더 빠르게 만들었습니다.이것으로 시간을 절약할 수 있기를 바랍니다!

효과: 이것이 바로 당신이 요청한 것입니다.

for a in $(git rev-list anybranch..mybranch); do echo -n "$a "; git branch --contains $a | xargs; done

당신은 엄격한 사람을 사용할 수 있습니다.git rev-list --all그러나 다른 곳이 아닌 분기에 대한 커밋에만 관심이 있는 경우, 소속된 분기를 선택하면 최소한 실제 차이가 제한되며 해당 분기에만 속하는 커밋을 한 눈에 볼 수 있습니다.

언급URL : https://stackoverflow.com/questions/14848274/git-log-to-get-commits-only-for-a-specific-branch

반응형