SHA-1 해시 값이 주어지면 커밋이 어떤 브랜치에서 나오는지 알 수있는 방법이 있습니까?
Ruby Grit을 사용하여이 작업을 수행하는 방법을 알려 주면 보너스 포인트입니다.
SHA-1 해시 값이 주어지면 커밋이 어떤 브랜치에서 나오는지 알 수있는 방법이 있습니까?
Ruby Grit을 사용하여이 작업을 수행하는 방법을 알려 주면 보너스 포인트입니다.
답변:
Dav는 정보가 직접 저장되지 않았다는 것이 맞지만 이것이 결코 찾을 수 없다는 것을 의미하지는 않습니다. 할 수있는 몇 가지가 있습니다.
git branch -a --contains <commit>
이것은 당신에게 주어진 커밋을 가진 모든 브랜치를 알려줄 것입니다. 커밋이 이미 병합 된 경우 분명히 유용하지 않습니다.
커밋이 수행 된 리포지토리에서 작업중인 경우 해당 커밋에 대한 행의 reflog를 검색 할 수 있습니다. 90 일이 지난 Reflog는 git-gc에 의해 제거되므로 커밋이 너무 오래된 경우 찾을 수 없습니다. 즉, 당신은 이것을 할 수 있습니다 :
git reflog show --all | grep a871742
커밋 a871742를 찾으십시오. 커밋의 약어 7 첫 번째 숫자를 사용해야합니다. 출력은 다음과 같아야합니다.
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
커밋이 "완료"분기에서 수행되었음을 나타냅니다. 기본 출력에는 약식 커밋 해시가 표시되므로 전체 해시를 검색하지 마십시오. 그렇지 않으면 아무것도 찾지 않습니다.
git reflog show
실제로는에 대한 별칭 git log -g --abbrev-commit --pretty=oneline
이므로 출력 형식을 사용하여 grep 할 수있는 다양한 항목을 만들고 싶다면 이것이 시작점입니다!
커밋이 이루어진 리포지토리에서 작업하지 않는 경우이 경우에 수행 할 수있는 최선의 방법은 reflog를 검사하고 커밋이 리포지토리에 처음 도입 된 시점을 찾는 것입니다. 운이 좋으면 커밋 된 지점을 가져 왔습니다. 커밋 트리와 reflog를 동시에 걸을 수 없기 때문에 조금 더 복잡합니다. reflog 출력을 구문 분석하여 각 해시에 원하는 커밋이 포함되어 있는지 확인하십시오.
이는 워크 플로우에 따라 다르지만 워크 플로우가 양호하면 개발 브랜치에서 커밋되어 병합됩니다. 다음과 같이 할 수 있습니다.
git log --merges <commit>..
주어진 커밋을 조상으로 갖는 병합 커밋을 볼 수 있습니다. (커밋이 한 번만 병합 된 경우 첫 번째 병합은 이후의 병합이어야합니다. 그렇지 않으면 몇 가지를 조사해야합니다.) 병합 커밋 메시지에는 병합 된 분기 이름이 포함되어야합니다.
이 작업을 의지하고 싶을 경우, 빠른 경우에도 병합 커밋 생성을 강제 실행 하는 --no-ff
옵션을 사용할 수 있습니다 git merge
. (너무 열심하지 마십시오. 과도하게 사용하면 혼란 스러워 질 수 있습니다.) 관련 질문에 대한 VonC의 답변 이이 주제에 도움이됩니다.
git describe
(주석) 태그 지점보다 더 중요하게 볼 수 있습니다에 대한 충분하다.
--no-ff
옵션을 사용하여 항상 병합 커밋이 있는지 확인할 수 있으므로 마스터로 병합 될 때 항상 지정된 커밋의 경로를 추적 할 수 있습니다.
-a
첫 번째 명령에 플래그를 추가하십시오.git branch -a --contains <commit>
-r
.
merge --no-ff
병합 할 때 분기 이름을 안정적으로 기록하는 데 사용 하십시오. 그러나 그렇지 않으면, 분기 이름을 임시 짧은 레이블로 생각하고 설명을 영구 레이블로 확약하십시오. "개발 중에 어떤 짧은 이름을 언급 했습니까?" "이 커밋이하는 일"만큼 중요한 질문이되어서는 안됩니다.
이 간단한 명령은 매력처럼 작동합니다.
git name-rev <SHA>
예를 들어, test-branch 는 지점 이름입니다.
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
이조 차도 다음과 같은 복잡한 시나리오에서 작동합니다.
origin/branchA/
/branchB
/commit<SHA1>
/commit<SHA2>
여기 git name-rev commit<SHA2>
에서 branchB를 반환합니다 .
git name-rev --name-only <SHA>
지점 이름 만 얻는 데 더 유용한 것으로 나타났습니다 . 내 질문은 ... 어떤 상황에서도 하나 이상의 지점을 반환 할 수 있습니까?
2013 년 12 월 업데이트 :
git-what-branch
(펄 스크립트, 아래 참조)는 더 이상 유지되지 않는 것 같습니다.git-when-merged
파이썬으로 작성된 대안으로 저에게 매우 효과적입니다.
" 특정 커밋을 포함하는 병합 커밋 찾기 "를 기반으로 합니다.
git when-merged [OPTIONS] COMMIT [BRANCH...]
커밋이 하나 이상의 분기로 병합 된시기를 찾으십시오. 지정된 지점으로
가져온 병합 커밋을 찾으십시오COMMIT
.특히 조상으로
BRANCH
포함 된 첫 번째 상위 히스토리에서 가장 오래된 커밋을 찾으십시오COMMIT
.
원래 답변 2010 년 9 월 :
Sebastien Douche 는 다음과 같이 트위트했습니다 (SO 답변 16 분 전).
git-what-branch : 커밋이 어떤 브랜치인지 또는 어떻게 지명 된 브랜치에 도달했는지 알아 봅니다.
개요
git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...
개요
요청 된 커밋을 명명 된 브랜치에 가져 오기 위해 커밋 및 병합의 가장 빠른 인과 경로를 기본적으로 알려주십시오. 명명 된 브랜치에서 커밋을 직접 수행 한 경우 가장 빠른 경로입니다.
가장 빠른 인과 경로는 커밋 시간에 의해 (
--topo-order
지정 되지 않은 한 ) 가장 이른 지명 된 브랜치로 병합 된 경로를 의미합니다 .공연
많은 브랜치 (예 : 수백)에 커밋이 포함 된 경우 시스템에서 시간이 오래 걸릴 수 있습니다 (Linux 트리의 특정 커밋의 경우 브랜치를 탐색하는 데 8 초가 걸렸지 만 후보 브랜치가 200 개가 넘음). 각 커밋에. 검사 할
특정 항목의 선택--reference-branch --reference tag
은 수백 개의 후보 분기가있는 경우 수백 배 더 빠릅니다.실시 예
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
이 프로그램은 관심있는 커밋의 체리 피킹 효과를 고려하지 않고 병합 작업 만 수행합니다.
git-what-branch
더 이상 유지되지 않는 것 같습니다. git-when-merged 는 Python으로 작성된 대안으로 저에게 매우 효과적입니다.
예를 들어, c0118fa
커밋 을 찾으려면 redesign_interactions
다음 을 수행하십시오 .
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
다음을 실행해야합니다.
git log c0118fa..HEAD --ancestry-path --merges
그리고 아래로 스크롤하여 마지막 병합 커밋 을 찾으십시오 . 어느 것이 :
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch 'redesign_interactions' into clean_api
최신 정보
또는 하나의 명령 만 :
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
git merge -m"Any String Here"
소스 및 대상 분기 정보가 모호해집니다.
Merge: f6b70fa d58bdcb
있습니다. 병합 커밋의 이름을 지정할 수 있습니다. 나는 중요하지 않다
git branch --contains <ref>
가장 확실한 "porcelain"명령입니다. "배관"명령만으로 비슷한 작업을 수행하려는 경우 :
COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
echo $BRANCH
fi
done
( 이 SO 답변의 교차점 )
khichar.anil 은 그의 답변에서 대부분을 다루었습니다 .
개정 이름 목록에서 태그를 제거하는 플래그를 추가하고 있습니다. 이것은 우리에게 :
git name-rev --name-only --exclude=tags/* $SHA
실험으로, 커밋 메타 데이터에 현재 체크 아웃 된 분기에 대한 정보를 저장하는 커밋 후 후크를 만들었습니다. 또한 정보를 표시하기 위해 gitk를 약간 수정했습니다.
https://github.com/pajp/branch-info-commits 에서 확인할 수 있습니다.
영업 이익이 결정하려고하는 경우 역사 특정 제작 한 커밋 지점에 의해 통과 된 후 reflog없이이 없습니다 ( "어떤 지점 커밋하는 것은 주어진 자사의 SHA-1 해시 값에서 유래 알아") 어떤 Git 객체 데이터베이스의 레코드는 커밋 히스토리에 바인딩 된 명명 된 분기를 표시합니다.
(댓글에 대한 답변으로 이것을 답변으로 게시했습니다.)
바라건대이 스크립트는 내 요점을 보여줍니다.
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
출력은 'Add f1'이있는 커밋이 원격 클론 / tmp / r2의 브랜치 b1 또는 b2에서 온 것인지 알 수있는 방법이 없음을 보여줍니다.
(여기서 출력의 마지막 줄)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
과 git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
명령은 무엇입니까?
$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
수율 376142d merge branches
및 $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
수율 376142d merge branches
-병합 커밋 요약을 보여줍니다. 병합이 생성 될 때 덮어 쓸 수 있으며 병합의 분기 기록을 혼란스럽게 할 수 있습니다.
쉘 종료 상태에 관심이있는 경우 아래를 사용하십시오.
branch-current
-현재 지점의 이름branch-names
-깨끗한 분기 이름 (한 줄에 하나씩)branch-name
-하나의 지점 만 반환해야합니다. branch-names
모두 branch-name
와 branch-names
A는 인수로 투입하고, 기본적 동의 HEAD
아무 것도 주어지지 않는 경우.
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
% git branch-name eae13ea
master
% echo $?
0
0
입니다.% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
입니다.종료 상태로 인해 안전하게 구축 할 수 있습니다. 예를 들어, 가져 오기에 사용되는 리모콘을 가져 오려면 다음을 수행하십시오.
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
지역 지점을 찾으려면
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
원격 지점을 찾으려면
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'